ES5以降では、Date.parse()に不正な日時を渡した場合、NaNを返す……が、不正な日時の解釈に実装によって違いがあることを今さら知った。タイトルのように2015-02-31を渡すと、Firefox 67はNaNを返すが、Chrome 75などでは良きにはからって、つまり2015-03-03とみなしてくれる。書式そのものの解釈の違いだけでなく、こんなところにも非互換性が埋まっていて、まんまとハマった。

Chrome 75やEdge 18、Node.js v12.0.0では以下のようになる。対してFirefox 67は2番目のみNaNを返す。

console.log(Date.parse("2015-02-28")); // 1425081600000
console.log(Date.parse("2015-02-31")); // 1425340800000
console.log(Date.parse("2015-03-03")); // 1425340800000

セケンではMoment.jsか何かを使い、Dateオブジェクトには一切触らないはずなので、あまり問題にならない。小さな書き捨てスクリプトで、おおむね日時っぽい文字列を何やらやる時にハマるかもしれない。


ES5の仕様では不正な日時ならNaNを返すとなっているが、どうなっていると不正なのかは明確ではない。日付と時刻の書式でDDは01から31まで許可されているので、2015-02-31は書式として正しく、不正な日時ではないと考えられる。一方で2015-02-31は存在しない日付なので、不正な日時だとも考えられる。

不正な日時の定義があいまいである以上、どちらの実装も間違ってはいない。のかもしれない。と思う。よう知らんけど。