Date 是 JS 中的重要的一個內建物件,其例項主要用於處理時間和日期,其時間基於 1970-1-1 (世界標準時間)起的毫秒數,時間戳長度為 13 位(不同於 Unix 時間戳的長度 10 位)。對於日期和時間,我們有無數個使用場景,因此需要特別注意一些細節和約定。
1. 建構函式
通過 new Date() 可以進行例項化,得到一個 Date 物件例項,值得注意的是如果直接執行 Date()
,將得到一個時間字串。
new Date();
new Date(value);
new Date(dateString);
new Date(year, month[, day[, hour[, minutes[, seconds[, milliseconds]]]]]);
<!– more –>
其中對建構函式的引數說明(參考 MDN ):
- 如果沒有輸入任何引數,則Date的構造器會依據系統設定的當前時間來建立一個Date物件。
- 如果提供了至少兩個引數,其餘的引數均會預設設定為1(如果沒有提供day引數)或者0。
- JavaScript的時間是由世界標準時間(UTC)1970年1月1日開始,用毫秒計時,一天由86,400,000毫秒組成。Date物件的範圍是-100,000,000天至100,000,000天(等效的毫秒值)。
- JavaScript的Date物件為跨平臺提供了統一的行為。時間屬性可以在不同的系統中表示相同的時刻,而如果使用了本地時間物件,則反映當地的時間。
- JavaScript 的Date物件提供了數個UTC時間的方法,也相應提供了當地時間的方法。UTC,也就是我們所說的格林威治時間,指的是time中的世界時間標準。而當地時間則是指執行JavaScript的客戶端電腦所設定的時間。
- 以一個函式的形式來呼叫JavaScript的Date物件(i.e., 不使用 new 操作符)會返回一個代表當前日期和時間的字串。
2. 空值處理
// 以chrome為例
new Date();
// Mon Oct 23 2017 23:38:02 GMT+0800 (CST)
new Date(false);
// Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
new Date(0);
// Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
new Date(null);
// Thu Jan 01 1970 08:00:00 GMT+0800 (CST)
new Date(``);
// Invalid Date
new Date(undefined);
// Invalid Date
3. 特別提示
[Firefox]
不支援帶 `-` 的完整時間,比如 new Date(`2012-07-08 00:00:00`) 為無效的值,而 new Date(`2012-07-08`) 是正確的值。
[month]
- new Date(year, month, ……) 中的month從0開始計算
4. 值的邊界
不同執行環境下的邊界值有差異, Chrome 下甚至連負值都能支援。在實際生產環境中,不僅需要考慮時間的展示,還需要考慮其儲存、計算等,因此在特定的場景下,我們需要儘可能考慮到資料庫和瀏覽器中 Date 的有效範圍。
以資料庫 Derby
儲存時間為例,其邊界為:
說明 | 邊界值 |
---|---|
最小的日期 | 0001-01-01 |
最大的日期 | 9999-12-31 |
最小的時間 | 00:00:00 |
最大的時間 | 24:00:00 |
最小的時間戳 | 0001-01-01-00.00.00.000000 |
最大的時間戳 | 9999-12-31-23.59.59.999999 |
在 mysql
中,其範圍定義為 1000-01-01
to9999-12-31
;
在 js
中,時間戳的最小值為 -8640000000000000
即公元前 271,821 年 4 月 20 日,最大值為 8640000000000000
,即 275,760 年 9 月 13 日。規範中時間範圍為 1970/1/1 前後 100,000,000
天。
5. 2038 年蟲
聽說,2038 年之後時間戳不夠用了。
在計算機應用上,2038年問題可能會導致某些軟體在2038年無法正常工作。所有使用UNIX時間表示時間的程式都將受其影響,因為它們以自1970年1月1日經過的秒數(忽略閏秒)來表示時間。這種時間表示法在類Unix(Unix-like)作業系統上是一個標準,並會影響以其C程式語言開發給其他大部份作業系統使用的軟體。在大部份的32位作業系統上,此“time_t”資料模式使用一個有正負號的32位元整數(signedint32)儲存計算的秒數。依照此“time_t”標準,在此格式能被表示的最後時間是2038年1月19日03:14:07,星期二(UTC)。超過此一瞬間,時間將會被掩蓋(wrap around)且在內部被表示為一個負數,並造成程式無法工作,因為它們無法將此時間識別為2038年,而可能會依個別實作而跳回1970年或1901年。錯誤的計算及動作可能因此產生。
實際上參考第 4 部分,Date 的上限綽綽有餘,大家可以拿起手頭的裝置測試一下 2038 年會出現怎樣的異狀。
6. 參考
1、EmacScript 語言規範 – http://ecma-international.org/ecma-262/5.1/#sec-15.9
2、Mysql 時間範圍 – https://dev.mysql.com/doc/refman/5.5/en/datetime.html
3、JS 時間戳邊界 – https://stackoverflow.com/questions/11526504/minimum-and-maximum-date