2017-04-20 38 views
8

爲什麼第一個輸入正常工作,但第二個輸入給了我5小時前的結果?相似的日期格式會產生意外的日期Javascript

new Date("2000-1-1") 
Sat Jan 01 2000 00:00:00 GMT-0500 (EST) 
new Date("2000-01-01") 
Fri Dec 31 1999 19:00:00 GMT-0500 (EST) 

我怎麼能得到第二個與我合作?

var a = new Date("2000-1-1"); // Sat Jan 01 2000 00:00:00 GMT-0500 (EST) 
 
var b = new Date("2000-01-01"); // Fri Dec 31 1999 19:00:00 GMT-0500 (EST) 
 
console.log(a, a.getTime()); 
 
console.log(b, b.getTime());

+3

顯示於瀏覽器,IE,和邊緣發生。 Firefox解析正確......也許使用[momentjs](https://momentjs.com/)可能會有用? javascript的'日期'往往是非常不一致 –

+0

有趣的是它與該特定年份無關,它與其他年份的行爲一樣 –

+1

第一個示例是非標準日期格式:https:// developer。 mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse,第二個是正確的,因爲它考慮了本地時間偏移量。 – evolutionxbox

回答

2

爲什麼你看到這是Date.parse()頁的MDN上實際描述(其中有很多細節周圍官方支持Date參數格式描述)的原因。具體做法是:在假定的時區

差異

鑑於「2014年3月7日」,解析()日期字符串假定本地時區,但給出的ISO格式,如「2014- 03-07「它將假定UTC時區(ES5和ECMAScript 2015)。因此,使用這些字符串生成的日期對象可能代表不同的時刻,具體取決於支持的ECMAScript版本,除非系統設置爲UTC本地時區。這意味着兩個顯示等同的日期字符串可能會導致兩個不同的值,具體取決於正在轉換的字符串的格式。

所以你看到的是兩兩件事的組合:

  1. 構造函數讀取您的正確格式的ISO日期值作爲UTC,由於沒有設置時區,並
  2. 它準確地確定您的本地計算機時區爲美國東部,並適當調整該值。

因此,您可以看到2000年1月1日午夜的美國東部時區版本UTC時間(或1999年12月31日晚上7點)。

由於您的第一個示例使用的是非標準格式(來自JS的視角),因此第一個假設並未發揮作用,並且假定本地時區爲值(瀏覽器 - 關於如何處理非標準格式的具體決定)。

0

黃金法則永遠不會使用Date構造函數或Date.parse解析字符串,因爲它們在很大程度上取決於實現。有許多怪癖。

根據ECMA-262,應將字符串「2000-01-01」解析爲有效的ISO 8601僅限日期的表格,but for timezone UTC+0000。像IE 8這樣的舊瀏覽器可能根本不會解析它,有些人可能會將其視爲本地。

字符串「2000-1-1」不正是ISO 8601格式,瀏覽器可能會回落到任何他們喜歡的啓發,包括:

  1. ,因爲它不是一個有效的ISO 8601日期返回無效日期格式
  2. 解析作爲本地日期2000年1月1日
  3. 治療如ISO 8601和解析爲UTC + 0000

至少1和2發生在當前的瀏覽器。

所以最好的選擇是使用帶解析器的庫並提供字符串的格式,或者如果您只有一種格式需要處理,請編寫一個簡單的函數。

/* Parse ISO 8601 date only form as local 
 
** @param {string} s - string in format YYYY-M[M]-D[D] 
 
** @returns {Date} If date parts out of range, returns invalid date 
 
*/ 
 
function parseISOLocal(s) { 
 
    var b = s.split(/\D/); 
 
    var d = new Date(b[0], --b[1], b[2]); 
 
    return isNaN(d) || d.getMonth() != b[1]? new Date(NaN) : d; 
 
} 
 

 
['2000-1-1','2000-01-01','2000-2-29','1900-2-29'].forEach(function(s) { 
 
    console.log(s + ' : ' + parseISOLocal(s).toString()); 
 
});