Day.jsの.tz.setDefault()が動かないと思ったけど使い方が間違ってただけだった
吉川@広島です。
dayjsのtimezoneプラグインに関するTips(?)です。
環境
- node 15.11.0
- dayjs 1.10.6
Timezoneプラグイン
Timezoneプラグインを使うことで、端末環境のタイムゾーンに左右されず時間を扱うことができます。
よくあるユースケースとして、「サーバのタイムゾーンはUTCだけどJSTで時間を扱いたい」といった場合が挙げられます。
Timezoneプラグインを使わない場合
まずはTimezoneプラグインを使わない例です。
// index.js const dayjs = require('dayjs') console.log(dayjs().format())
こちらのコードを次のコマンドで実行します。
TZ=utc node index.js
あえて TZ=utc
で環境変数TZにutcを指定しています。すると出力は次のようになります。
2021-08-06T14:59:15+00:00
今この記事を書いている時間がJSTの2021/8/6 23:59なので、ちょうど9時間前の時間が出ています。UTC時間ということですね。
Timezoneプラグインを使って.tz('Asia/Tokyo')を指定
TZ=utc
でもJSTで時間を出力したいニーズに応えるのが次の例です。
const dayjs = require('dayjs') const utc = require('dayjs/plugin/utc') const timezone = require('dayjs/plugin/timezone') dayjs.extend(utc) dayjs.extend(timezone) console.log(dayjs().tz('Asia/Tokyo').format())
Timezoneプラグインを読み込み、 .tz('Asia/Tokyo')
で日本のタイムゾーンを指定しています。 こちらのコードを先程と同じコマンドで実行します。
TZ=utc node index.js
出力は以下でした。
2021-08-07T00:04:50+09:00
今、2021/8/7 00:04なので、意図通りの値ですね(日が変わってしまった)。+09:00もUTCを基準として9時間プラス(=日本時間)ということで適切です。
Timezoneプラグインを使って.tz.setDefault('Asia/Tokyo')を指定
ただ、常に日本時間で扱いたいという場合に、dayjsのメソッドを使うたびに毎回 .tz('Asia/Tokyo')
を書くのは大変です。そこで、デフォルトのタイムゾーンを設定できるsetDefault()があります。
動かない?
では、こちらを使ったコードを書いてみます。
const dayjs = require('dayjs') const utc = require('dayjs/plugin/utc') const timezone = require('dayjs/plugin/timezone') dayjs.extend(utc) dayjs.extend(timezone) dayjs.tz.setDefault("Asia/Tokyo") console.log(dayjs().format())
また同じコマンドで実行します。
TZ=utc node index.js
出力は以下でした。
2021-08-06T15:08:50+00:00
今、00:08なので、12時間前のUTC時間となってしまっていますね。 .setDefault('Asia/Tokyo')
が効いていない・・・?
正しい使い方
ということで「dayjs setDefault not working」みたいなキーワードで検索したところ次のissueを発見しました。
dayjs.tz.setDefault doesn't work as expected. · Issue #1195 · iamkun/dayjs
こちらから、「setDefaultを使った場合、.tz()を呼んだ際の挙動に影響を与える」という点を理解しました。
つまり、下記が正です。
const dayjs = require('dayjs') const utc = require('dayjs/plugin/utc') const timezone = require('dayjs/plugin/timezone') dayjs.extend(utc) dayjs.extend(timezone) dayjs.tz.setDefault("Asia/Tokyo") -console.log(dayjs().format()) +console.log(dayjs().tz().format())
このように変更して実行すると出力は以下でした。
2021-08-07T00:13:32+09:00
ちゃんと日本時間を出力してくれました。
つまり、自分は最初 setDefault
を .tz()
の呼び出し自体を省略できる宣言と勘違いしていたのですが、そうではなく、 .tz()
の引数(= 'Asia/Tokyo'
)を省略できるものであり、 .tz()
自体は都度呼んであげる必要があるということでした。
説明がわかりにくかったかもしれませんが、伝わったでしょうか?
同じハマり方をする人がいるかもしれないと思い共有でした。参考になれば幸いです。