データベースのdatetime型カラムの日時をJavaScriptでフォーマットして出力しようとしたら、Chromeでは正常に表示されるのにFirefoxでは表示されないという状態に陥った。

調べたところ、なんと、JavaScriptのDateオブジェクトはブラウザ毎に取り扱えるフォーマットが異なることを知りました。いやぁ、こんなところにも面倒なクロスブラウザの壁があったとは…。

──ということで、この際、徹底的に調べてみようと思い、下記のようなスクリプトを組んでみた。

var datetimes = {
  'YYYY-MM-DD HH:mm:ss': '2015-09-08 10:26:31', 
  'YYYY-MM-DDTHH:mm:ss': '2015-09-08T10:26:31', 
  'YYYY-MM-DDTHH:mm:ssZ': '2015-09-08T10:26:31Z', 
  'YYYY-MM-DDTHH:mm:ss.sssZ': '2015-09-08T10:26:31.000Z', 
  'YYYY-MM-DDTHH:mm:ss+hh:mm': '2015-09-08T10:26:31+09:00', 
  'YYYY/MM/DD HH:mm:ss': '2015/09/08 10:26:31', 
  'YYYY/MM/DDTHH:mm:ss': '2015/09/08T10:26:31', 
  'YYYY/MM/DDTHH:mm:ssZ': '2015/09/08T10:26:31Z', 
  'YYYY/MM/DDTHH:mm:ss.sssZ': '2015/09/08T10:26:31.000Z', 
  'YYYY/MM/DDTHH:mm:ss+hh:mm': '2015/09/08T10:26:31+09:00'
};
var html = '<ol>';
for (var k in datetimes) {
  console.info({ k: new Date(datetimes[k]) });
  html += '<li><label>'+k+'</label>: '+new Date(datetimes[k])+'</li>';
}
html += '</ol>';
document.write(html);

そして、各ブラウザでの出力結果は、

date format Chrome(45.x) firefox(40.x) Safari(5.1.7) Opera(31.0) IE11
YYYY-MM-DD HH:mm:ss Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時)) Invalid Date Invalid Date Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時)) Invalid Date
YYYY-MM-DDTHH:mm:ss Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 10:26:31 GMT+0900 Invalid Date Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時))
YYYY-MM-DDTHH:mm:ssZ Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 19:26:31 GMT+0900 Tue Sep 08 2015 19:26:31 GMT+0900 (“Œ‹ž (•W€Žž)) Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時))
YYYY-MM-DDTHH:mm:ss.sssZ Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 19:26:31 GMT+0900 Tue Sep 08 2015 19:26:31 GMT+0900 (“Œ‹ž (•W€Žž)) Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 19:26:31 GMT+0900 (東京 (標準時))
YYYY-MM-DDTHH:mm:ss+hh:mm Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 10:26:31 GMT+0900 Tue Sep 08 2015 10:26:31 GMT+0900 (“Œ‹ž (•W€Žž)) Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時))
YYYY/MM/DD HH:mm:ss Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 10:26:31 GMT+0900 Tue Sep 08 2015 10:26:31 GMT+0900 (“Œ‹ž (•W€Žž)) Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時)) Tue Sep 08 2015 10:26:31 GMT+0900 (東京 (標準時))
YYYY/MM/DDTHH:mm:ss Invalid Date Invalid Date Invalid Date Invalid Date Tue Sep 08 2015 12:26:31 GMT+0900 (東京 (標準時))
YYYY/MM/DDTHH:mm:ssZ Invalid Date Invalid Date Invalid Date Invalid Date Invalid Date
YYYY/MM/DDTHH:mm:ss.sssZ Invalid Date Invalid Date Invalid Date Invalid Date Invalid Date
YYYY/MM/DDTHH:mm:ss+hh:mm Invalid Date Invalid Date Invalid Date Invalid Date Invalid Date

──となった。
う~む、すべてのモダンブラウザで利用できる日時フォーマットはYYYY-MM-DDTHH:mm:ssZYYYY-MM-DDTHH:mm:ss.sssZYYYY-MM-DDTHH:mm:ss+hh:mmYYYY/MM/DD HH:mm:ssの4つしかない。
そのうち、タイムゾーンのローカル時間で返してくれるのは、YYYY-MM-DDTHH:mm:ss+hh:mmYYYY/MM/DD HH:mm:ssの2つとなる。

まぁ、汎用的な処理を考えた場合、タイムゾーン補正値の指定は何気に面倒なので、使い勝手が良いのはYYYY/MM/DD HH:mm:ssの一択になる(可用性が低いなぁ…)。

ちなみに、MySQLなどのdatetime型カラムの値は‘YYYY-MM-DD HH:mm:ss`なので、この値をベースにしてJavaScriptでDateオブジェクトを生成する場合、

var datetime = new Date(datetime_from_db.replace(/\-/g, '/'));

──と云うように-/に変換してあげれば良い。