Date.now() 與 new Date()

本篇探討一些前端的時間戳記理解,提供給大家參考:

大家都知道 Date.now 就是一個 Date 物件的方法,可以快速拿到當下的時間,但究竟拿到的是什麼呢?

快速理解

Date.now() 與 new Date() 直接調用後的機制相同,都是取得 UTC 的當下時間,也就是全球同步,不論你今天在哪,瀏覽器是什麼,使用這兩個都會拿到相同的時間值。

如果你只是單純要拿當下時間,不會有什麼大問題,但如果需要進行某個定時來比對時,事情就會變得麻煩了,比如你要做個倒數計時器,或是一個頁面關閉的判斷式。

主要問題

Date.now() 與 new Date() 不難理解,但如果是 new Date('2020-03-18T00:00') 呢?拿到的時間在世界各地都會相同嗎?

深入探討

我們查閱資料可以知道,上面問題的指定時間字符串,因為沒有帶上任何標註時區的字段,所以 js 會自動依照瀏覽器的時區進行設定,假設在台灣的話,就是指定創建一個TW 3/18 00:00,那台灣時間也就是GMP+8,所以可以知道標準時間其實為UTC 3/17 16:00,實際設定時間慢了我們 8 小時。

首先我們做個比喻,把程式碼比喻成一個商店的牌子,並且把瀏覽器的時區想成商店的位置,而用戶就是某個消費者,當今天日本的商店公告在日本凌晨12點關閉時,對台灣的客人來說,半夜11點時該商店就已經關閉了,

假設現在我是一個用戶,在 GMT+8 的2020-03-18T00:00這時間瀏覽網頁,並且瀏覽器時區被硬性設定在 UTC 時間,原本的期望是在這時間之後開啟網頁某些內容,但因為瀏覽器時區實際是慢 8 小時,所以瀏覽器內的時間其實還在2020-03-17T16:00,並未到達設定的 2020-03-18T00:00,所以網頁上的內容被未如期出現。

總結整理

發生原因:

雖然預設時區是依照用戶自己設定的瀏覽器時區,所以大部分情況下在前端用 js 拿時間都是沒有問題的,但像是一些App內瀏覽器,可能App供應商為了世界各地的經營考量,會將該瀏覽器時區統一設定,避免用戶自行更改時區導致問題。

此時在該瀏覽器下取得的時間,就會與實際使用者當下的時間有所差別,也就會發生類似上面的,使用者已經12點了,但App內瀏覽器還沒的問題。

解決辦法:

根據不同的用戶地區,將前端程式碼的時間預先加或減實際瀏覽器時區的時間差,例如我希望讓我 UTC 時區的瀏覽器,能夠在 GMP+8 時區的玩家在半夜 00 點看到上線的活動,那我就必須在程式碼中設定前一天的 16:00。

常見狀況

通常,對於時區換算這件事會由後端完成,前端拿到絕對的 UTC 時間後再進行判斷就不會有問題,但如果必須完全依賴前端完成時間判斷時,就必須知道前端 Date 物件的行為模式,記住下面這句來自 W3School 的說明

when getting a date object without specific timezone, it returns UTC time with the browser timezone.(same time in different zone)

when setting a date object without specific timezone, it set the date with the browser timezone.(different UTC time in different zone)

所以當瀏覽器時區跟使用者時區不同,而你又一定要進行 set Date 物件的動作時,那就是要進行換算的時候了。

Last Updated:
Contributors: johnnywang