Ruby

ruby の Date.parse の私の知らなかった機能

ruby の Date.parse に思いがけない機能があったのでメモ。

いずれも class Date のリファレンスマニュアルには載っていなかった。


Date.parse("20")

二桁の数値を入れると、今月のn日目( n=="01" の場合、1日 )になる。


ruby2.6

Date.parse("01").strftime("%Y.%m.%d")

#=> "2019.04.01"

Date.parse("30").strftime("%Y.%m.%d")
#=> "2019.04.30"

Date.parse("00").strftime("%Y.%m.%d")
#=> ArgumentError: invalid date

Date.parse("31").strftime("%Y.%m.%d")
#=> ArgumentError: invalid date



Date.parse("110")

三桁の数値を入れると、今の年の n日目( n=="001" の場合、元旦 )になる。


ruby2.6

Date.parse("001").strftime("%Y.%m.%d")

#=> "2019.01.01"

Date.parse("000").strftime("%Y.%m.%d")
#=> ArgumentError: invalid date

Date.parse("365").strftime("%Y.%m.%d")
#=> "2019.12.31"

Date.parse("366").strftime("%Y.%m.%d")
#=> ArgumentError: invalid date



Date.parse("19110")

つづいて、五桁の場合。

最初の2桁が年。0068 は 2000年以降。6999 は 1999年かそれ以前。

あとの3桁が、元旦を1とした日付。001 なら 1月1日で、365でうるう年でなければ 12月31日。


ruby2.6

Date.parse("68001").strftime( "%Y.%m.%d" )

#=> "2068.01.01"

Date.parse("69001").strftime( "%Y.%m.%d" )
#=> "1969.01.01"

Date.parse("12345").strftime( "%Y.%m.%d" )
#=> "2012.12.10"

Date.parse("19000").strftime( "%Y.%m.%d" )
#=> ArgumentError: invalid date

Date.parse("19001").strftime( "%Y.%m.%d" )
#=> "2019.01.01"

Date.parse("19365").strftime( "%Y.%m.%d" )
#=> "2019.12.31"

Date.parse("19366").strftime( "%Y.%m.%d" )
#=> ArgumentError: invalid date



Date.parse("2019110")

そして七桁の場合。

最初の四桁が年。これが厄介。

00000068 なら、2000年から2068年。

00690099 なら、1969年から1999年。

それ以外はそのまま年になる。

あとの3桁が、元旦を1とした日付。001 なら 1月1日で、365でうるう年でなければ 12月31日。


ruby2.6


Date.parse("0000001").strftime( "%Y.%m.%d" )
#=> "2000.01.01"

Date.parse("0068365").strftime( "%Y.%m.%d" )
#=> "2068.12.30"

Date.parse("0069001").strftime( "%Y.%m.%d" )
#=> "1969.01.01"

Date.parse("0099365").strftime( "%Y.%m.%d" )
#=> "1999.12.31"

Date.parse("0100001").strftime( "%Y.%m.%d" )
#=> "0100.01.01"

Date.parse("9999365").strftime( "%Y.%m.%d" )
#=> "9999.12.31"



それ以外の桁数

1桁から100桁まで調べてみたけど、上記以外はArgumentError: invalid dateになる。

受け入れる桁数は 2, 3, 5, 7桁。一桁の素数の集合と一致。


元号対応

M, T, S, H は元号とみなされてよろしくやってくれる。

手元ではまだ 2.6.3 になっていないので、令和には対応していない。

※ 2.6.3 が "R1.5.1" をどうするのかは、未確認。

明治999年とか、明治0年とかでもエラーにせずに適当にやってくれる。

怖いのは、M, T, S, H 以外のアルファベットは無視されて西暦になるところ。


ruby2.6.2

Date.parse("M45.1.1").strftime( "%Y.%m.%d" )

#=> "1912.01.01"

Date.parse("M45.8.1").strftime( "%Y.%m.%d" )
#=> "1912.08.01"

Date.parse("M46.1.1").strftime( "%Y.%m.%d" )
#=> "1913.01.01"

Date.parse("M999.1.1").strftime( "%Y.%m.%d" )
#=> "2866.01.01"

Date.parse("M0.1.1").strftime( "%Y.%m.%d" )
#=> "1867.01.01"

Date.parse("T12.3.4").strftime( "%Y.%m.%d" )
#=> "1923.03.04"

Date.parse("S56.7.8").strftime( "%Y.%m.%d" )
#=> "1981.07.08"

Date.parse("H31.4.20").strftime( "%Y.%m.%d" )
#=> "2019.04.20"

Date.parse("R1.5.1").strftime( "%Y.%m.%d" )
#=> "2001.05.01" ( 2.6.2 なので R は無視されて西暦になる )


ちなみに、"㍻31.4.20", "平31.4.20", "平成31.4.20" は、元号名が無視されて 2031年になる。


まとめ


意味

Date.parse("20")
今月の20日

Date.parse("110")
今年の110日目

Date.parse("19110")
19年の110日目

Date.parse("2019110")
2019年の110日目

Date.parse("H31.4.20")
平成31年4月20日

いずれも、現象を確認しているだけでソースコードは見ていない。