JavaScriptの日付のパースはあまりに微妙

JavaScriptの日付や時刻の処理ははまりどころが多いのでも有名ですが、こんなはまりポイントを発見したので、まとめておきます。JavaScriptのDateクラスを使えば日付時刻を記録できるオブジェクトです。getTime()メソッドで1970年1月1日からのミリ秒経過時間(基準からの経過時間)を得て計算するのが一般的なパターンです。文字列で与えられた日付や時刻があったとき、Dateクラスのスタティックメソッドのparseにより、基準からの経過時間が得られます。MDNのドキュメントには、RFC2822 or ISO 8601に従った文字列ならOKとなっています。前者は「Oct 5, 2014」、後者は「2014-10-05」といった文字列です。

では、「2014-10-5」でも一瞬いいのじゃないかなと思って調べてみました。実は、この形式はISO 8601のルール上では間違いです。月と日は常に2桁である必要があります。まず、Chromeです。最初の2行を見れば、一見すると、2014-10-05でも、2014-10-5でもいいように見えます。しかし、Date.parse()の数値を見ると、右側の実行結果の2行目になりますが、ちょっとだけ違う数値になっています。3月3日について、月日の1ないしは2桁の全ての組み合わせてやってみたのが、引き続く4行です。最初の2行に戻ると、9時間の差があります。

shot8846

つまり、Chromeでは、ISO 8601に従った「2014-10-05」は、日本時間の10月5日のAM 9:00であり、そうでないものは標準時での10/5 0:00になるとうことですね。つまり、日本時間にすると9時間前なので、ちょっとだけ小さな数字になります。

Firefoxを見てみましょう。なんと、「2014-10-5」などのISO 8601のルールをはずれたものは、エラーとなります。正しいといえば正しい。

shot8847

Chromeで次のような式を計算したら、-1になったんですよね。0になることを期待しますが、そうではなかった。それで気づきました。それに、Firefoxでは結果がでないということもありますね。

Date.parse("2014-10-5") / (60*60*24*1000) - Date.parse("2014-10-05") /(60*60*24*1000)

ほんとにはまりどころ満載です。