IE の Date.parse と微妙に違う ISO 8601 の話


 客先から「IE で、日付が表示されてないよ」と問い合わせがありました。Google Chrome だと問題ないので、気付きませんでした。よくあることのような気がするので、調べた結果をまとめます。

 問い合わせのあった部分は、データベースに格納された日時を文字列で出力して javascript の Date.parse にかけていました。たとえば、次のような処理です。Date.parse("2014-09-22 07:16:37.294268") 指摘されたとおり、これをIEで実行すると NaN が帰ってきました。短くして Date.parse("2014-09-22") でも同じです。なんということでしょう。

 Microsoft のドキュメント には、最初に Date.parseISO 8601 形式で解釈しようとする、失敗したら別の方法で解釈する…というような事が書いてあります。よくよく眺めてみると、データベースから取り出した日時は微妙に ISO 8601 を満たしていません。日付と時間の区切り文字が半角スペースになっています。wikipedia によると、正しい ISO 8601 は T で区切られるもののようです。そこで、今度は修正して Date.parse("2014-09-22T07:16:37.294268") を実行しました。今度は、期待したとおりの結果が帰ってきました。

 使っているデータベースは PostgreSQL です。どうしてこのような独自形式で日時を返すようになっているのでしょうか。Postgres のドキュメント の 8.5.2 節を読んでみると、ISO 8601 で出力していることになっているようです。ここには T の区切り文字は登場しません。よくわかりませんね。

 ExtJS にある Ext.Date.parse を使えば、T のあるなしに関わらず解析できます。ただし、このメソッドは第二引数に、解釈に使用するパターンを与えなくてはいけません。ISO 8601 で解釈させるには "c" を与えます。たとえば、Ext.Date.parse("2014-09-22 07:16:37.294268", "c") のように書きます。とりあえずこれを使うことにして問題は解決しましたが、PostgreSQL の挙動や Date.parse の挙動は釈然としないものがあります。

追記: Document Mode が IE7 や IE8 の場合、Date.parse が ISO 8601 に対応していないようです。危険ですね。