foomin10のhatenablog

なんかてきとーに

PowerShell の datetime のパースの挙動を適当に確認してみた

実際に動かして調べたメモ。ドキュメントとかは知らね。


まず、[\t\n ,.]+ あたりで区切り、項ごとに英語のパーサ、日本語のパーサに渡していく。

項ごとに 年、月、日、曜日 を確定していき確定しなかった項を最後に推定する。きっとそんな感じ。

年がない場合は今年、年以外ならとりうる一番小さい値になる。


最初は、英語のパーサ。独自の区切りとして “-” “/” とかがある。複数だとダメなやつとか数のすぐとなりじゃないとダメとか、“ - - ” がパーサを超えて(?)ダメだったり。

年が 2 桁の場合は、1930-2029年。(00 から 29 は 2000 を、30 から 99 は 1900 を足した値)

年が 1 桁の場合は、2000-2009年。

ラテン文字は、ignore case。

英語月名・英語曜日は long or 3 letter。

  • 4桁年 or 3桁年
  • 英語月名
  • [ 日にち ]

の組み合わせは全て対応してる。

"2016-dec" | date -f "yyyy-MM-dd HH:mm:ss"
"dec-2016" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2016-12-01 00:00:00

"2016/dec/5" | date -f "yyyy-MM-dd HH:mm:ss"
"2016/5/dec" | date -f "yyyy-MM-dd HH:mm:ss"
"dec/2016/5" | date -f "yyyy-MM-dd HH:mm:ss"
"dec/2/2016" | date -f "yyyy-MM-dd HH:mm:ss"
"5/2016/dec" | date -f "yyyy-MM-dd HH:mm:ss"
"5/dec/2016" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2016-12-05 00:00:00

"8 Nov 015" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 0015-11-08 00:00:00

英語月名と 2 桁か 1 桁の数2つの場合は、年と日は日付として正しくなる方に割り当てられる。どちらも正しいなら先頭を年とする。

"10/dec/31" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2010-12-31 00:00:00
"10/dec/32" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 1932-12-10 00:00:00

"11/feb/29" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2029-02-11 00:00:00
"12/feb/29" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2012-02-29 00:00:00

英語月名と数1つの場合は、月の前なら年として、月の後ろなら日にちとする。

"31 dec" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 1931-12-01 00:00:00
"dec 31" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2017-12-31 00:00:00
"dec 32" | date -f "yyyy-MM-dd HH:mm:ss"
# エラー # 1932-12-01 とはならない

数3つの場合、3 桁か 4 桁があればそれを年として、残りを先頭から月日とする。なければ先頭から年月日とする。

数2つの場合、3 桁か 4 桁があればそれを年として、残りを月とする。なければ先頭から月日とする。

"9-8-7" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2009-08-07 00:00:00
"9-8" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2017-09-08 00:00:00
"9-800" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 0800-09-01 00:00:00

"13-5" | date -f "yyyy-MM-dd HH:mm:ss"
# エラー # 2017-05-13 とはならない

すべて英語のパーサなら後ろに GMT を含めることができる。UTC としてパースするが Kind は “Local” のまま。

"Mon, 20 Feb 2017 03:38:40 GMT" | date -f "yyyy-MM-dd HH:mm:ss zzz"
#=> 2017-02-20 12:38:40 +09:00
"03:38 GMT" | date -f "yyyy-MM-dd HH:mm:ss zzz"
#=> 2017-02-20 12:38:00 +09:00

曜日はどこに入れてもいいが、検証される。日付の特定には利用されない。

("20 Feb 2017" | date).DayOfWeek
#=> Monday
"20 Feb Mon 2017" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2017-02-20 00:00:00
"20 Feb Tue 2017" | date -f "yyyy-MM-dd HH:mm:ss"
# エラー

("10/Dec/2031" | date).DayOfWeek
#=> Wednesday
"10/Dec/2031, Wednesday" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2031-12-10 00:00:00
"10/Dec/31, Wednesday" | date -f "yyyy-MM-dd HH:mm:ss"
# エラー # 2010-12-31 (Friday) とパースしようとして、曜日検証でエラー

日本語のパーサは、“年” “月” “日” の後ろで区切ってパースする。

"2016年2月5日" | date -f "yyyy-MM-dd HH:mm:ss"
"5日2月, 2016年" | date -f "yyyy-MM-dd HH:mm:ss"
" ,,2016年 .,.., 2月 .,., .5日." | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2016-02-05 00:00:00

"4月6日" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2017-04-06 00:00:00

"98年2月" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 1998-02-01 00:00:00

"98年2日" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 1998-01-02 00:00:00

"16年" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2016-01-01 00:00:00

"3月" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2017-03-01 00:00:00

"25日" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2017-01-25 00:00:00

"Mon, 2017年2月20日" | date -f "yyyy-MM-dd HH:mm:ss"
"2017年2月20日, 月" | date -f "yyyy-MM-dd HH:mm:ss"
"2017年2月20日 月曜日" | date -f "yyyy-MM-dd HH:mm:ss"
#=> 2017-02-20 00:00:00

よくわからないけど すごい

とりあえず、おわり。