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
よくわからないけど すごい
とりあえず、おわり。