[Luxon] 顯示 UTC 時間而非當地時間

Luxon 是一套輕巧但強大的時間處理 library,可以幫助我們快速解析來源時間字串,並處理好時區問題,不過預設處理時區有時候也會帶來一些困擾,今天就筆記一下如何用 Luxon 來處理各種時區問題。

問題

快速看個例子:

DateTime
  .fromISO('2021-01-09T18:00:00Z')
  .toFormat('yyyy/MM/dd');
// 2021/01/10

我們的日期來源是 2021-01-09T18:00:00Z 這個 UTC 時間,使用 Luxon 的 DateTime.fromISO() 可以輕易的解析出這個時間,單純以 UTC 時間來看日期是 2021-01-09,而經過 toFormat('yyyy/MM/dd') 後的日期則是 2021/01/10 看起來似乎是差了一天。

為什麼會這樣呢?那是因為 Luxon 在解析完字串後,會貼心地幫我們轉為當地的時區時間,我們可以用 toISO() 來看一下轉換後的時間格式:

DateTime
  .fromISO('2021-01-09T18:00:00Z')
  .toISO()
// 2021-01-10T02:00:00.000+08:00

以我目前在台灣的時區 +08:00 來說,實際上的 ISO 時間為:2021-01-10T02:00:00.000+08:00,可以看到確實幫我們轉成了當地的時區時間。

這麼做的好處是,通長時間資料是會存在 server 端的,而 server 端就不用去煩惱儲存的格式,統一使用 UTC 時間即可,當前端收到資料要顯示時,透過 Luxon 轉換後,則可以單純的使用當地時間去思考就好。

這麼做當然用意是好的,但有時候我們就是希望顯示 UTC 時間該怎麼辦呢?

使用 setZone

Luxon 也提供的 setZone 來幫助我們指定時區

DateTime
  .fromISO('2021-01-09T18:00:00Z')
  .setZone('utc')
  .toFormat('yyyy/MM/dd');
// 2021/01/09

DateTime
  .fromISO('2021-01-09T18:00:00Z')
  .setZone('utc')
  .toISO()
// 2021-01-09T18:00:00.000Z

如此一來就可以正常顯示 UTC 時間啦!

透過 setZone 可以幫助我們快速的指定各種時區顯示時間,因此也不用侷限在 UTC 時間,例如想轉換成美國的芝加哥時間,則可以設定 setZone('America/Los_Angeles'),各個時區對應可以在 wiki 上都查得到,我也會附上連結在最後的參考資料內。

另外,在解析 ISO 時間時,其實也可以直接指定時區,不過我還是偏愛使用 .setZone() 這種書寫方式,所以單純當作筆記參考用:

DateTime
  .fromISO('2021-01-09T18:00:00Z', { zone: 'America/Los_Angeles' })
  .toISO()
// 2021-01-09T10:00:00.000-08:00

本日小節

Luxon 真的是功能非常強大的 library,又不像 moment 那麼肥大,實際上 Luxon 也是 moment 團隊內的成員打造出來的,目標也是提供更輕量且標準的時間處理工具。

開發系統難免會遇到各種時間問題,Luxon 提出了很棒的解決方案,文件也非常豐富,以後有機會遇到其他特別狀況再提出來討論。

參考資料

如果您覺得我的文章有幫助,歡迎免費成為 LikeCoin 會員,幫我的文章拍手 5 次表示支持!
[Angular 大師之路] Angular 12 預設開啟 strict mode 的生存之道
[Ramda] 使用 sortWith 輕鬆達成多欄位排序條件

有任何問題或建議嗎?歡迎留言給我