Moment.jsで時刻をユーザーのTime Zoneに合わせて表示する

Webシステムで多言語対応をするとき、サーバー側でTimeZoneを変換して、レンダーしてもいいのですが、ユーザーのTimeZoneをあらかじめ保存するなど、何かしらの方法でサーバーにTimeZoneを伝える必要があり、大変です。

そんなとき、ユーザーのクライアントのLocaleを利用すると便利です。

Moment.jsを利用して、それを表現する方法をご紹介します。

Moment.jsとは

Moment.jsはJavaScriptで時刻を扱うときに便利なライブラリです。時刻をフォーマットに従って表示したり、N時間後がいつかを計算したり、様々な時刻に関する計算が簡単に行えるようになります。

今回はTimeZoneを扱うので、TimeZoneについて拡張できるMomentTimezone.jsも同時に使っていこうと思います。

これらは、以下のようにパッケージマネージャーで簡単にインストールすることができます。

npm install moment-timezone
yarn add moment-timezone

もちろん、zipをダウンロードして、配置してもOKです。

TimeZoneを自動で合わせる

今回は<time>タグのdatetime属性に時刻を入れたら、自動でクライアントのTimeZoneに合わせて時刻表示が変わるように作っています。

<!-- あらかじめdatetime属性にの値を入れておく -->
<time class="timezone" datetime="2022-01-01T00:00:00Z"></time>

<!-- moment.js, moment-timezone-with-data.jsをロード -->
<script src="script/moment.min.js"></script>
<script src="script/moment-timezone-with-data.min.js"></script>

<script>
    // ここで"Asia/Tokyo"のような文字列が取れる!
    var timezoneName = moment.tz.guess(); 

    var elements = document.querySelectorAll('time.timezone');
    var format = 'YYYY/MM/DD HH:mm:ss';
    elements.forEach(function(el){
        var dt = el.dateTime; // <time>タグのdatetime属性の値を取得
        var timeStr = moment(dt).tz(timezoneName).format(format);
        el.innerText = timeStr;
    });
</script>

ポイントはmoment.tz.guess()という部分です。ここで、Asia/Tokyoのような文字列を取得できます。この機能はJavaScriptの国際化APIを利用して取得しているのですが、一部、国際化APIを利用できないブラウザでは他の情報から推測してTimeZoneを表示してくれるそうです。

MomentTimezone.jsのドキュメントを確認してみてください。

この文字列を利用してmoment(時刻).tz(timezoneName)のようにすると、時刻のタイムゾーンを変更したデータを作ることができます。

まとめ

サーバー側は時刻を気にせず実装することができるので、TimeZoneによるバグの心配なく安心して開発を進められます。

グローバル対応が必要なアプリケーションは比較的少ないからこそ、多言語対応やTimeZoneは分かりやすいやり方でやりたいですね。