LoginSignup
6
2

More than 5 years have passed since last update.

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

Last updated at Posted at 2019-04-20

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日

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

6
2
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
2