摘要:經(jīng)過一步步后發(fā)現(xiàn)問題在此客戶時(shí)區(qū)為美國(guó)東部時(shí)區(qū)夏令時(shí)明明寫的號(hào),為什么生成的對(duì)象是號(hào)的因?yàn)榘阉馕鰹?,時(shí)區(qū)為。美國(guó)東部時(shí)區(qū)是減小時(shí)的,于是就變成了前一天??梢詡魅胍粋€(gè)日期字符串來生成對(duì)象的,官方規(guī)定日期字符串需要符合或者的格式。
TL;DR
new Date 和 Date.parse 在格式化某些日期字符串的時(shí)候,時(shí)區(qū)具有不確定性,最好用 moment.js 這類工具去處理。
不確定的日期字符串事情的起源是客戶跟我說網(wǎng)頁上的某個(gè)日期總是比實(shí)際日期少一天。經(jīng)過一步步 debug 后發(fā)現(xiàn)問題在此:
js// 客戶時(shí)區(qū)為美國(guó)東部時(shí)區(qū)夏令時(shí) new Date("2015-03-31") // Mon Mar 30 2015 20:00:00 GMT-0400 (EDT)
明明寫的 31 號(hào),為什么生成的對(duì)象是 30 號(hào)的?因?yàn)?new Date 把它解析為 2015-03-31 00:00:00 ,時(shí)區(qū)為 UTC 。美國(guó)東部時(shí)區(qū)是減 4 小時(shí)的,于是就變成了前一天 20:00:00 。
那么 new Date 傳入的時(shí)間字符串有沒有規(guī)律可循呢?
混亂的規(guī)律new Date 和 Date.parse 使用的是同樣的解析規(guī)律,只是一個(gè)返回 Date object 另一個(gè)返回毫秒數(shù)。為了方便查看結(jié)果,以下例子只用 new Date 。但請(qǐng)記住它們遵循一樣的規(guī)律。
new Date 可以傳入一個(gè)日期字符串來生成對(duì)象的,官方規(guī)定日期字符串需要符合 RFC2822 或者 ISO8601 的格式。拿上面的日期舉個(gè)例子,前者可以寫成 "Mar 31 2015" 后者可以寫成 "2015-03-31" 。
如果日期字符串不符合這兩種標(biāo)準(zhǔn),new Date 對(duì)結(jié)果概不負(fù)責(zé)……
不過就算符合標(biāo)準(zhǔn)了,結(jié)果還是有點(diǎn)不同的。看幾個(gè)例子:
jsnew Date("Mar 31 2015") // Tue Mar 31 2015 00:00:00 GMT-0400 (EDT) new Date("2015-03-31") // Mon Mar 30 2015 20:00:00 GMT-0400 (EDT)
RFC2822 的格式如果不帶時(shí)區(qū),new Date 會(huì)當(dāng)做本地時(shí)區(qū)處理,而 ISO8601 格式則會(huì)當(dāng)做 UTC 時(shí)區(qū)處理。
是有點(diǎn)繞人,但只要記住這個(gè)規(guī)律不就完了嗎?騷年你太天真了…… 因?yàn)?ES6 草案為了簡(jiǎn)化這種情況,規(guī)定所有不帶時(shí)區(qū)的字符串都默認(rèn)為本地時(shí)區(qū)。注意這是草案,所以結(jié)果你懂的。
解決方案一種解決方案是每次格式化日期都嚴(yán)格指定時(shí)區(qū),以防止各種幺蛾子情況出現(xiàn),比如:
jsnew Date("2015-03-31T00:00:00-04:00") // Tue Mar 31 2015 00:00:00 GMT-0400 (EDT)
不過鑒于人都是懶惰的,這種情況交給工具做更靠譜,比如 moment.js 。
jsmoment("2015-03-31").toDate()參考鏈接
Date.parse() - JavaScript | MDN
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/85605.html
摘要:對(duì)象對(duì)象實(shí)例表示單個(gè)時(shí)間點(diǎn)盡管名為它同樣被用來處理時(shí)間。在內(nèi)部日期表示自年月日起到現(xiàn)在的毫秒數(shù)。這意味著傳入相同的參數(shù)在不同電腦上可能會(huì)有不同的結(jié)果。在沒有任何有關(guān)時(shí)區(qū)的信息的情況下會(huì)將日期視為結(jié)果會(huì)自動(dòng)針對(duì)當(dāng)前的計(jì)算機(jī)時(shí)區(qū)進(jìn)行轉(zhuǎn)換。 在 JavaScript 中處理日期可能會(huì)很復(fù)雜,我們一起學(xué)習(xí) Dates 所有的怪癖并掌握如何使用它。 簡(jiǎn)介 在 JavaScript 中處理日期可能...
摘要:在內(nèi)部,日期以年月日以來的毫秒數(shù)表示。以毫秒為單位記錄原因。你也可以使用將返回一個(gè)時(shí)間戳以毫秒為單位而不是對(duì)象。如果您使用天數(shù)計(jì)算超過一個(gè)月,則不會(huì)出現(xiàn)錯(cuò)誤,日期將轉(zhuǎn)到下個(gè)月數(shù)月,小時(shí),分鐘,秒和毫秒都是如此。 簡(jiǎn)介showImg(https://segmentfault.com/img/bVbfH0e?w=777&h=512); JavaScript通過強(qiáng)大的對(duì)象為我們提供日期處理功...
摘要:在內(nèi)部,日期以年月日以來的毫秒數(shù)表示。以毫秒為單位記錄原因。你也可以使用將返回一個(gè)時(shí)間戳以毫秒為單位而不是對(duì)象。如果您使用天數(shù)計(jì)算超過一個(gè)月,則不會(huì)出現(xiàn)錯(cuò)誤,日期將轉(zhuǎn)到下個(gè)月數(shù)月,小時(shí),分鐘,秒和毫秒都是如此。 簡(jiǎn)介showImg(https://segmentfault.com/img/bVbfH0e?w=777&h=512); JavaScript通過強(qiáng)大的對(duì)象為我們提供日期處理功...
摘要:在內(nèi)部,日期以年月日以來的毫秒數(shù)表示。以毫秒為單位記錄原因。你也可以使用將返回一個(gè)時(shí)間戳以毫秒為單位而不是對(duì)象。如果您使用天數(shù)計(jì)算超過一個(gè)月,則不會(huì)出現(xiàn)錯(cuò)誤,日期將轉(zhuǎn)到下個(gè)月數(shù)月,小時(shí),分鐘,秒和毫秒都是如此。 簡(jiǎn)介showImg(https://segmentfault.com/img/bVbfH0e?w=777&h=512); JavaScript通過強(qiáng)大的對(duì)象為我們提供日期處理功...
摘要:而實(shí)際上將表示日期的字符串傳遞給構(gòu)造函數(shù),也會(huì)在后臺(tái)調(diào)用。如果省略其他參數(shù),則統(tǒng)統(tǒng)假設(shè)為時(shí)間年月日午夜時(shí)時(shí)間年月日下午構(gòu)造函數(shù)也會(huì)模仿,但有一點(diǎn)明顯不同日期和時(shí)間都基于本地時(shí)區(qū)而非創(chuàng)建。不過構(gòu)造函數(shù)仍與接收的參數(shù)相同。 Date類型 ECMASCript中的Date類型是在早期中Java中的java.util.Date類基礎(chǔ)上構(gòu)建的。為此Date類型使用自UTC(國(guó)際協(xié)調(diào)時(shí)間)1970...
閱讀 3095·2021-11-24 10:47
閱讀 3853·2021-11-02 14:43
閱讀 2244·2021-09-26 10:15
閱讀 2303·2021-09-08 09:35
閱讀 580·2019-08-30 12:45
閱讀 2789·2019-08-29 17:04
閱讀 3221·2019-08-26 14:05
閱讀 1272·2019-08-26 12:10