平時對 Date 很多内容都一知半解,每次一用到 Date 就需要查資料,着實惱火。 故此文記錄關于 JS 日期操作那些我不知道的事。
基礎問題
Date.prototype.getTime() 傳回的數字是什麼?
官方對getTime 函數對定義是
The getTime() method returns the number of milliseconds* since the Unix Epoch
getTime() 函數傳回從 Unix Epoch 開始到目前 Date 所指時間經過的毫秒數。
Unix Epoch 是什麼呢?
1970年1月1日(UTC/GMT的午夜)
是以 getTime() 傳回的數字是
從 1970年1月1日0時0分0秒開始到目前 Date 對象所指時間所經過的毫秒數。
例如:
getTime() 和你所在的時區也有關系,我國的标準時間是中原標準時間,在東八區,是以比英國格林威治時間(GMT)的 0 時區晚 8 個小時。是以我定義的 1970年1月1日使用 getTime 函數得到 -2880000,即 8 小時。
GMT 和 UTC 是什麼,有什麼差別?
GMT(格林尼治标準時間) 和 UTC(協調世界時) 是計算世界時間的兩種标準。
GMT 根據地球的自轉和公轉來計算時間,也就是太陽每天經過位于英國倫敦郊區的皇家格林威治天文台的時間就是中午12點。UTC是根據原子鐘來計算時間,目前世界上最精确的原子鐘50億年才會誤差1秒。因為地球的自傳正在緩速變慢,會導緻 GMT 計算有誤差,是以 UTC 比 GMT 更加精确。UTC 時間被認為能與GMT 時間互換,但 GMT 時間已不再被科學界所确定。
PS:兩個都是 0 時區的時間,例如:UTC +8 = 中原標準時間。
Date.getMonth() 為什麼要從 0 開始
誰能想到這是 Java 埋的坑,因為 Javascript 的 Date 實作方案是 JDK1.0 的方案,是以坑也一樣。 Javascript 之父用一句 Make It Look Like Java 調侃了這個坑也告訴了我們答案。
問題來了,Java 擷取月份為什麼要從 0 開始呢?
- 說法 1: 可能是因為舊的 C 語言日期 API 是這樣的,那麼舊的 C 語言日期 API 為什麼是這樣呢?...不套娃了。
- 說法 2:計算機裡面所有東西都從 0 開始
- 說法 3:從 0 開始做月份計算更加容易
例如 12 月的下一個月份是 1 月,不過為了計算出 1 月你會做以下計算:
12
我們可以用 12 取餘快速修複上面的問題
(
但是當遇到 11 月的時候...
(
您可以在添加月份之前先減去1,然後再進行取餘運算,最後再加1,就可以修複上面的問題...也可以解決這個“基本問題”。
((
現在我們來看看如果月份的數字是 0 - 11,會有什麼問題?
(
所有月份的表現一緻,無需較複雜的解決方案。
時間戳是什麼?
常指 unix 時間戳,上文提到過:從1970年1月1日(UTC/GMT的午夜)開始所經過的秒數。 擷取時間戳的代碼:
Math
常用方法
定義時間的方法
傳入時間格式的字元串
new
不同的浏覽器實作有差異,強烈不建議使用字元串初始化/解析日期。建議使用傳入數字初始化日期對象。相同的浏覽器針對不同的定義方式也有些許差異。
例子1:
new
例子2:在 2020年以前的,Firefox 和 Chrome 針對以下代碼實作有差異。
Date
傳入多個時間機關的數字
new
傳入 Unix 時間戳
new
時間的加減法
減法
首先,需要将你的日期轉化為 Date 對象,然後直接使用加減符号計算差。得到的結果是和或差的毫秒數,再将毫秒轉化成你需要的格式。例如 2020-01-01 和 2020-01-02 差多久?
new
如果結果是要計算差多少天,即是 86400000 除以 1000得到秒數,再除以 60 得到分鐘數,以此類推。
86400000
加法
兩個 Date 相減能得到毫秒,那理所當然地某個 Date 加上毫秒數就可以等于另一個日期了。例如 2020-01-01 加上 86400000 毫秒,就等于 2020-01-02 No!No!No!
new
我還是太年輕了,跨類型的兩個對象,強行加在一起,不甜。
1.轉換成數字相加
将 new Date(2020,0,1) 轉換成毫秒,來到整形的世界,快樂地計算。
(
2.使用 JS 内置方法
加減年、月、日、時、分、秒。例如:
var
不同的時間機關的加法使用的方法不同,可以根據下表選擇對應的方法。
比較時間的大小
擷取毫秒數,進行數字大小的比較。
new
擷取不同格式的目前時間
toString()
new
toLocaleString()
new
toUTCString()/toGMTString()
new
GMT 已經不被推薦使用了,原因在上文提到過:UTC 比 GMT 精确。
toISOString()
new
傳回 ISO 格式 (ISO 8601)的日期。
ISO 格式日期的規則是生成格式為
YYYY-MM-DDTHH:mm:ss.sssZ或者
±YYYYYY-MM-DDTHH:mm:ss.sssZ的
24 位到 27 位字元串。
YYYY-MM-DD
THH:mm:ss.sssZ 裡面的 T 是分隔日期和時間的符号。
YYYY-MM-DDTHH:mm:ss.sss
Z裡面的 Z 是時區的占位符,可以不寫時區用 Z 代替是 0 時區,也可以使用 2020-09-17T00:20:06+08:00 代表東八區。
資料
- MDN-Date
- 知乎-UTC和GMT什麼關系?
- 知乎-JavaScript中的Date對象取值month為什麼是從0開始的?
- stackoverflow-why-is-january-month-0-in-java-calendar