ruby の Date.parse
に思いがけない機能があったのでメモ。
いずれも class Date のリファレンスマニュアルには載っていなかった。
Date.parse("20")
二桁の数値を入れると、今月のn日目( n=="01" の場合、1日 )になる。
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" の場合、元旦 )になる。
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桁が年。00
〜68
は 2000年以降。69
〜99
は 1999年かそれ以前。
あとの3桁が、元旦を1とした日付。001
なら 1月1日で、365
でうるう年でなければ 12月31日。
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")
そして七桁の場合。
最初の四桁が年。これが厄介。
0000
〜0068
なら、2000年から2068年。
0069
〜0099
なら、1969年から1999年。
それ以外はそのまま年になる。
あとの3桁が、元旦を1とした日付。001
なら 1月1日で、365
でうるう年でなければ 12月31日。
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 以外のアルファベットは無視されて西暦になるところ。
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日 |
いずれも、現象を確認しているだけでソースコードは見ていない。