AWS Lambdaで日本時間を取得するのに少し苦労したので、それについて書き残します。
今回Lambda(Node.js)上の開発で、Dateオブジェクトに東京のタイムゾーンを設定しても日本時間を取得できないということがありました。
const currentHour = new Date(new Date().toLocaleString({ timeZone: 'Asia/Tokyo' })).getHours();
原因はよく分からないのですが、UTC(協定世界時)で計算されており、日本の9時間前の時刻を取得してしまいます。
ならばと、取得したUTCの時間にプラス9時間してあげればよくない?天才!と思って以下のように書きました。
const currentHour = new Date().getHours()+9
が、よく考えたらこれだとUTCで16時以降の場合にプラス9時間した値が25以上になってしまうことに気づきました。よく考えなくても気づこう。
そこでいくらか調べているうちに最終的にこちらを参考にさせていただき、以下のコードで日本時間を取得できました。
const currentHour =new Date(Date.now() + ((new Date().getTimezoneOffset() + (9 * 60)) * 60 * 1000)).getHours();
なんだか複雑ですが、これでマシンのデフォルトがUTC/JST(日本標準時) 関係なく日本時間を取得できるようになります。
上の式を簡単に説明すると、以下の二つの時間(ミリ秒)の足し算になっています。
①現在時刻 Date.now()
②足す時間 (new Date().getTimezoneOffset() + (9 * 60)) * 60 * 1000
最終的に①②の和(ミリ秒)をgetHours()で時間(hrs)に直しています。
①はいいとして、②のDate().getTimezoneOffset()
では、UTCとの時間差を分単位で取得しています。
UTCなLambdaではUTCとの時間差がないので0を取得することになります。
一方、ローカル環境などデフォルトでJST(日本時間)を取得するマシンだと、9時間先に進んでいるので-540(60分×9)を取得します。
(+540ではなく-540になるのは、取得したタイムゾーンに-540したら0(UTC)になるという考えだと推測しています)
そうすると各マシンで②の足す時間は以下のような計算結果になります。
(new Date().getTimezoneOffset() + (9 * 60)) * 60 * 1000
・UTCの場合: (0 + 540) * 60 * 1000 = 32,400,000ミリ秒(9時間)
・JSTの場合: (-540 + 540) *60 * 1000 = 0
UTCなマシンでは現在時刻(UTC)に9時間プラスし、JSTなマシンでは現在時刻(UTC+9時間)に0時間足す計算になるので、どちらの時間を基準にしたマシンでも日本時間(UTC+9時間)を取得できるようになっています。
あとがき
世界標準時はイギリスのグリニッジ天文台の標準時「GMT(Greenwich mean time)」と学校で習った気がしましたが、プログラミングをしていてよく聞くのはUTCですよね。
何が違うのかと少し調べたら、GMTは平均太陽時を基準とするのに対し、UTCは原子時計を基準としていてUTCの方がより精密だそうです。
よく分かりませんが、ほぼ同義として受け止められているみたいなのであまり気にしないことにします。
コメント