コード日進月歩

しんくうの技術的な小話、メモ、つれづれ、など

RubyのDate.parseはオプションを特につけず、年月日を2桁表記すると上位2桁を補完できるが独特の動きをするので気をつける

割と理由が読み取れない不思議な仕様なのでメモ

環境

$ ruby -v
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-darwin18]

挙動と例

Date.parse には下記のような仕様がある。

年が "00" から "99" の範囲であれば、 年の下2桁表現であるとみなしこれを補います。 この振舞いを抑止したい場合は、ヒントとして、complete に false を与えます。 - singleton method Date.parse (Ruby 2.5.0)

年度のところは西暦の上二桁を自動で埋めてくれるとのこと、ただし何で埋めてくれるかは書いていないので調べた。

まずは 00

Date.parse("00/1/1")
=> #<Date: 2000-01-01 ((2451545j,0s,0n),+0s,2299161j)>

2000年扱い。それでは99だと2099にでもなるのかなと思いきや…

Date.parse("99/1/1")
=> #<Date: 1999-01-01 ((2451180j,0s,0n),+0s,2299161j)>

1999年扱い。この1900年代だと2000年代の切り分けはオプションとかではない様子。境目をしらべる。

Date.parse("70/1/1")
=> #<Date: 1970-01-01 ((2440588j,0s,0n),+0s,2299161j)>
Date.parse("69/1/1")
=> #<Date: 1969-01-01 ((2440223j,0s,0n),+0s,2299161j)>
Date.parse("68/12/31")
=> #<Date: 2068-12-31 ((2476747j,0s,0n),+0s,2299161j)>

69までは1900年代扱いで、68年になると2000年代になる。UNIXTIMEとしては1970年1月1日はじまるなので不思議な仕様。

ちなみにこの自動補正を加えたくない場合は第二引数をfalseにすると、単純な足し上げ数値になる。

Date.parse("99/1/1",false)
=> #<Date: 0099-01-01 ((1757218j,0s,0n),+0s,2299161j)>
Date.parse("1098/1/1",false)
=> #<Date: 1098-01-01 ((2122103j,0s,0n),+0s,2299161j)>

参考リンク