Date對象二三事

一些概念

Date是什麼?

Date是JavaScript用來操做日期時間的對象,以常規函數調用它,會返回一個表明當前時間的字符串,而不是一個日期對象,即:javascript

typeof Date()          // "string"
typeof (new Date())    // "object"

除了文獻[6]中提到的返回是否依賴參數以外,返回的類型也有差異,所以,能夠更嚴謹地說明:Date()不管參數如何都只返回當前時間的字符串,而new Date()則會根據參數返回相應時間對象(打印出來的是toString方法執行的結果)。html

JavaScript的時間戳又是什麼?

JavaScript的時間戳定義爲從格林威治時間1970年01月01日00時00分00秒(北京時間1970年01月01日08時00分00秒)起到如今的總毫秒數,對於每個時刻而言,都有獨一無二的時間戳與它對應。前端

時間戳,無關乎時區,對於同一時刻而言,不一樣時區雖然表現的時間不相同,但時間戳是相同的。
想象這樣一個場景:當前是格林威治時間2018-07-20 00:00:00,服務端位於中國(東八區,時間是2018-07-20 08:00:00),前端位於洛杉磯(西七區,時間是2018-07-19 18:00:00),而前端的頁面想要顯示出服務端的日期,若是兩端之間經過時間戳1532044800000來傳遞,服務端是7月20日,而客戶端顯示的則是7月19日,這並不符合咱們的預期,因此正確的應該傳遞服務端所在時區的日期「2018-07-20」才能知足咱們的需求。java

UTC 與 GMT

UTC(Coordinated Universal Time,以UTC爲縮寫是英文與法文的折衷縮寫)協調世界時間,是標準時間,以通過平均太陽時(以格林威治時間GMT爲準),地軸運動修正後的新時標以及以「秒」爲單位的國際原子時所綜合精算而成的時間。不過由於時區的影響,沒有國家會直接使用它做爲當地時間的。segmentfault

GMT(Greenwich Mean Time,以GMT爲縮寫)格林威治時間,其實是一個時區(time zone),以時間來看的話,是英國倫敦郊區的皇家格林威治天文臺的標準時間(零時區),因爲零時區的特殊性常與UTC混用,所以在使用上GMT與UTC表明的也是相同的時間。瀏覽器

Date構造函數的參數們

Date構造函數的參數能夠分爲四類:函數

  • 無參數
  • (單參數)時間戳
  • (單參數)時間字符串
  • 至少三個參數以上,表明年、月、日、時、分、秒、毫秒

無參數、多參數和時間戳的狀況比較簡單,注意傳參的類型是Number就好了,而字符串的方式則比較複雜,咱們單獨拿出來研究。code

時間字符串格式標準共有兩種:ISO 8601和RFC 2822。orm

ISO 8601標準[3]

ISO 8601標準格式「YYYY-MM-DDTHH:mm:ss.sssTZD」,其中:htm

  • YYYY-MM-DD是年月日,HH:mm:ss.sss是時分秒毫秒;
  • TZD表明時區(Chrome默認爲「Z」,Safari默認爲當前時區),能夠是「Z」即爲標準時間UTC,或者是「±hh:mm」;
  • T是日期與時間的區分:
    • 若是T換成空格,Chrome中則與有T時表示的相同,Safari則做爲「Invalid Date」

舉個栗子,對比一下2018年7月20日零點在東八區(或默認時區)和GMT的不一樣:

new Date('2018-07-20T00:00:00+00:00')     // Fri Jul 20 2018 08:00:00 GMT+0800 (中國標準時間) --> 標準時間的0點對應東八區的8點
new Date('2018-07-20T00:00:00+08:00')     // Fri Jul 20 2018 00:00:00 GMT+0800 (中國標準時間) --> 與 new Date('2018-07-20T00:00:00')一致

new Date('2018-07-20 00:00:00')        // Chrome中:Fri Jul 20 2018 00:00:00 GMT+0800 (中國標準時間)
new Date('2018-07-20 00:00:00')        // Safari中:Invalid Date

RFC 2822標準[4]

RFC2822標準格式「day-of-week DD month-name YYYY HH:mm:ss ±hhmm」,但DD與month-name交換的格式也是能夠被識別的。

舉個栗子,Chrome和Safari表示時間的格式就是這個標準,如:

new Date('Fri 20 Jul 2018 00:00:00 +0800')    // Fri Jul 20 2018 00:00:00 GMT+0800 (中國標準時間)

另外,還有一種格式「YYYY/MM/DD」,我沒找到標準文檔,由於文獻[5]中提到與ISO8601日期格式在默認時區上有些不一樣,這裏也單獨列出來:

new Date('2018/07/21')        // Sat Jul 21 2018 00:00:00 GMT+0800 (中國標準時間)
new Date('2018-07-21')        // Sat Jul 21 2018 08:00:00 GMT+0800 (中國標準時間)

相同的狀況,文獻[2]也有說明:

given an ISO format such as "2014-03-07" it will assume a time zone of UTC (ES5 and ECMAScript 2015).

Date的getter們

有了本文前面的知識,Date的getter會更容易理解一些。

  • toISOString:返回完整的ISO8601格式,如「2018-07-19T16:00:00.000Z」;
  • toUTCString(toGMTString):以RFC2822格式返回標準時間的時間字符串,如「Thu, 19 Jul 2018 16:00:00 GMT」;
  • toLocaleDateString:返回當前時區的日期部分,以「YYYY/MM/DD」這種格式,如「2018/7/20」;
  • toLocaleTimeString:返回當前時區的時間部分,以「上午/下午 hh:mm:ss」格式,如「上午 12:00:00」(這裏指的實際上是0點);
  • toLocaleString:返回當前時區的完整時間,如「2018/7/20 上午12:00:00」;
  • toDateString:返回RFC2822格式中日期部分,如「Fri Jul 20 2018」;
  • toTimeString:返回RFC2822格式中時間部分,如「00:00:00 GMT+0800 (中國標準時間)」
  • toString:返回RFC2822格式的完整時間,如「Fri Jul 20 2018 00:00:00 GMT+0800 (中國標準時間)」;
  • valueOf:返回Number格式的時間戳,如「1532016000000」;

總結

在時間的漩渦裏掙扎了一個多星期,終於把文章寫完了。這一切仍是源於「JavaScript的時間戳又是什麼?」裏提到的場景,本來我天真的覺得每一個時區都有本身的時間戳,但實際上並不是如此。會有這樣的誤差也是概念不夠清晰理解的緣故,當我意識到這點就開始找資料調研起Date對象。標準文檔仍是同樣抽象難啃,更坑爹的是一個小小的Date對象都有這麼多的標準和差別,感覺真的如同文獻5的標題「What A Mess!」。

最後列一下瀏覽器版本吧:

  • Chrome版本:版本 67.0.3396.99(正式版本) (64 位)
  • Safari版本:11.0.2 (13604.4.7.1.6)

參考文獻

  1. 《The Difference Between GMT and UTC》https://www.timeanddate.com/t...
  2. https://developer.mozilla.org...
  3. ISO 8601 https://www.w3.org/TR/NOTE-da...
  4. RFC 2822 https://tools.ietf.org/html/r...
  5. 《JavaScript and Dates, What a Mess!》http://blog.dygraphs.com/2012... 
  6. 《JS原生Date類型方法的一些冷知識》https://segmentfault.com/a/11...
相關文章
相關標籤/搜索