中村@アールテクニカ
アールテクニカの中村です。
先日担当した案件で、JavaScriptのDateオブジェクトを使用するコードを書きましたが、Chromeでは正常に動作しているのにSafariでは正常に動作しないという現象が発生しました。
何が原因だったのか、どう対応すればいいのか解説したいと思います。
APIから取得したデータに、2016-09-30T12:34:56という形式と、2016/09/30T12:34:56という形式が混在していたため、最初は、タイムゾーンを付加して2016-09-30 12:34:56+09:00という形式に変換してDateオブジェクトの初期化引数としていたのですが、この実装ではChromeでは正常に動作していましたが、Safariでは日付がデコードできていませんでした。
そこで、2016-09-30T12:34:56+09:00にしたところ両方の環境で正常動作するようになりました。
2016-09-30T12:34:56+09:00は、ISO 8601の拡張形式と言う正式に規格化された日付書式ですが、2016-09-30 12:34:56+09:00は正式な規格に沿った書式ではなくブラウザによって対応状況が異なっていたのでした。
これで原因はわかりましたが、正式な規格ではないYYYY/MM/DDはSafariでも対応していた記憶があるので、各ブラウザがどの書式に対応しているか調べてみることにしました。
検証内容
ISO 8601と慣習的に使用されているYYYY/MM/DD hh:mm:ssを中心に各ブラウザの日付書式の対応状況を確認してみます。
実際に検証する日付の書式は、日付の区切りがハイフンかスラッシュ、日付と時間の区切りが"T"か空白、タイムゾーン指定があるか無いかの組み合わせで合計8通りとしました。
var dates = [ "2016-09-20T12:00:00", "2016-09-20T12:00:00+09:00", "2016-09-20 12:00:00", "2016-09-20 12:00:00+09:00", "2016/09/20T12:00:00", "2016/09/20T12:00:00+09:00", "2016/09/20 12:00:00", "2016/09/20 12:00:00+09:00" ]; var s = ""; for (var i=0; i < dates.length; i++) { var date = new Date(dates[i]); s += 'new Date("' +dates[i] + '"): ' + date + '\n'; } console.log(s);
各ブラウザで上記のコードを実行した結果は次のようになりました。
日付がハイフン区切り
まずは、日付がハイフン区切りの結果を確認します。
日時"T"区切り、タイムゾーンなし
2016-09-30T12:00:00
IE8以下とSafari 5.x以外は対応かと思いきや、タイムゾーン省略時の解釈がブラウザごとに異なり、FirefoxとIE9以降では、日本時間と解釈するため、そのまま日本時間の2016年9月30日 12:00:00となりますが、ChromeとSaferi 9.xは世界標準時と解釈するため日本時間の2016年9月30日 21:00:00となります。ブラウザによって時間がズレてしまうので実質的に使えないでしょう。
日時"T"区切り、タイムゾーンあり (ISO 8601拡張形式)
2016-09-30T12:00:00+09:00
IE8以下は対応していませんが、それ以外はすべて対応しています。IE9以降対応でよいならこの書式で問題ないでしょう。
日時が空白区切り
2016-09-30 12:00:00、2016-09-30 12:00:00+09:00
日時が空白区切りは、タイムゾーンあり・なし共に、IE、Safari系がすべて非対応となっています。RDBからSQLで取得する場合この形式になっていることが多いので、サーバからのデータをJavaScript側で使用する場合は注意が必要です。
日付がスラッシュ区切り
日時"T"区切り、タイムゾーンなし
2016/09/30T12:00:00
ほとんどのブラウザが対応しておらず、IEがタイムゾーンなしの場合のみ一応日時として解釈してくれますが、世界標準時+2時間という謎のタイムゾーンになります。
日時"T"区切り、タイムゾーンあり
2016/09/30T12:00:00+09:00
この書式はどのブラウザも非対応でした。
日時空白区切り、タイムゾーンなし
2016/9/30 12:00:00
この書式は、今回確認したすべてのブラウザであればすべて対応していました。古いブラウザも対応するならこの書式がベストでしょう。ただし、タイムゾーンは日本時間と解釈されるので元データにタイムゾーン指定がある場合は注意が必要です。
日時空白区切り、タイムゾーンあり
2016/09/30 12:00:00+09:00
ChromeとSafari 9.xのみ対応でした。
結論
結論としては、対象が最新ブラウザであるならISO 8601形式(YYYY-MM-DDThh:mm:ss+zz:zz)を使用するのがベスト、古いブラウザも対象になるなら、タイムゾーンに注意してYYYY/MM/DD hh:mm:ss形式を使用するのがよいでしょう。
中村@アールテクニカ
アールテクニカのSE兼プログラマ。Web系のサーバサイド・フロントエンドからスマホ・PCのネイティブアプリまでソフトウェア開発全般が守備範囲。最近はハードウェア開発にも興味あり。