備忘ログ

チラシの裏的備忘録&メモ

和暦、旧暦、西暦(ユリウス暦とグレゴリウス暦)の相互変換をR上で行う関数を含むパッケージを作ってGithubに上げた

和暦、旧暦、西暦(ユリウス暦グレゴリウス暦)の相互変換をR上で行う関数を含むパッケージを作ってGithubに上げた。

github.com

remotes::install_github("indenkun/jcalendaR")

でインストールできる。

年月日をすべて入力する必要があるが、その代わり明治5年以前も正確に変換できるようになっている……と思う。

Example

library(jcalendaR)

和暦から西暦、西暦から和暦への変換ができる。和暦というのは実際に日本で使われている暦であり、明治5年以前はいわゆる旧暦と一致するようになっている。

和暦から西暦への変換。

wareki2seireki("令和3年1月1日")
## [1] "2021/1/1"

西暦から和暦への変換。

seireki2wareki("2021/1/1")
## [1] "令和3年1月1日"
# 上杉謙信のWikipediaの命日は天正6年3月13日らしい。ユリウス暦も指定できる。
wareki2seireki("天正6年3月13日", calendar = "julian")
## [1] "1578/4/19"

明治6年以降は日本ではグレゴリウス暦が採用されているが、旧暦を調べることもできる。

旧暦から西暦を調べる。

kyureki2seireki("令和3年1月1日")
## [1] "2021/2/12"

西暦から旧暦を調べる。

seireki2kyureki("2021/1/1")
## [1] "令和2年11月18日"
# sys.Date()で今日の旧暦日を調べることもできる
seireki2kyureki(Sys.Date())
## [1] "令和2年12月15日"

和暦と旧暦の相互変換もできるようにしている。明治5年以前は和暦と旧暦は一致するが、その際も一回計算している。

和暦から旧暦。

wareki2kyureki("令和3年1月1日")
## [1] "令和2年11月18日"

旧暦から和暦。

kyureki2wareki("平成31年1月1日")
## [1] "平成31年2月16日"

旧暦の指定した年に閏月があるかどうかを調べることもできる。理論型か閏月の値で答えを返す。

existence_leap.month("明治2")
## [1] FALSE
existence_leap.month("明治2", existence = "number")
## [1] NA
existence_leap.month("明治3", existence = "logical")
## [1] TRUE
existence_leap.month("明治3", existence = "number")
## [1] 10

旧暦の指定した年の指定した月が何日あるか。閏月を指定した場合、その年に閏月がないならその旨を警告文で出す。

number_kyureki.month("明治2", 1)
## [1] 30
number_kyureki.month("明治2", "閏1")
## Warning: There are no leap months in that year.

## [1] NA
number_kyureki.month("明治3", "閏10")
## [1] 29

内部的に、ユリウス通日を計算しているので、その関数も使えるようにしている。計算式はWikipediaの計算式をそのまま使っている。引数を指定するとユリウス暦でも計算できる。

ユリウス通日から西暦。

jdn2calendar(2459216)
## [1] "2021/1/1"

西暦からユリウス通日

calendar2jdn("2021/1/1")
## [1] 2459216

あとは注意とかREADMEにちょろちょろ書いている。

雑感・所感

日本の暦法は何度か変わっていることや元号がいくつか分岐があってめんどくさいが、内部でユリウス通日に変換してデータ参照すれば行けることは薄々わかっていたのでようやっと腰を上げて取り組んでみた。基本動作は旧暦の1年1月から2100年12月までの1日のユリウス通日のデータと参照しながら日付を計算しているという力技仕様。自力で旧暦を計算するのはできる人はできるのかもしれないが自分には無理。

変換できないパターンが入力された場合の警告文表示が一致していないので今後そこらへんを調整していきたい。

あとは、ドキュメントが適当英語から始まる適当の嵐なのでちゃんとしたい。

この関数群を作るにあたり、内部で文字列処理やデータフレームや日付の処理があって今どきのモダンな処理なら{tidyvers}{stringr}{dplyr}{lucidate}を使うのが定番というか、簡単に書けるのだけれど今回はあえて頑張って{base}だけで書いてみた(内部データは{tidyvers}で作ったけど)。

{base}だけで書くメリットは

  • 依存関係が基本的に存在しないのでユーザー側に余計なパッケージをインストールさせなくても良い。
  • Rらしさを感じる要素は人それぞれだと思うがapply系なんか{base}`を工夫して使うとなんかRらしさを感じて楽しい。

一方でデメリットは(もちろんなれやスキルによるが)

  • {tidyvers}を始めとする今どきの書き方に慣れていると書きづらい。関数間で統一された感がないのも辛い。
  • 入れ子形式などが増えるので可読性がやや下がるし、併せてメンテナンス性が下がる。
  • {tidyvers}のあの関数を使えば簡単に実現できるものが{base}だとちょっとめんどくさかったりする。
  • 文字列処理が辛い。

と思った。

デメリットが多いように見えるが、小さいものでたまにやる分には修行的な意味で楽しいと思った。