日期构造函数:数字参数与字符串参数在某些情况下给出不同的日期

时间:2012-04-22 15:59:47

标签: javascript date constructor

首先,我认为时区可能与此有关。我在EST / EDT。另外,我正在使用chrome 17 / linux进行测试。

现在,假设我创建了两个这样的日期:

// December 5

dateFromNumbers = new Date(2020, 11, 5);
dateFromString = new Date("2020-12-5");

似乎这些日期应该具有相同的时间戳,并且它们会:

+dateFromNumbers == +dateFromString; // true

......至少在这种情况下。但在某些情况下,他们不会:

// December 15

dateFromNumbers = new Date(2020, 11, 15);
dateFromString = new Date("2020-12-15");

+dateFromNumbers == +dateFromString; // false

这里发生了什么?

dateFromNumbers; // Tue Dec 15 2020 00:00:00 GMT-0500 (EST)
dateFromString;  // Mon Dec 14 2020 19:00:00 GMT-0500 (EST)

在这种情况下,dateFromString看起来比dateFromNumbers提前5小时(EST是GMT - 5,我确定它与某种方式有关)。

这似乎会影响到10月到12月的月末。这是一个小提琴,可以很容易地看出哪些日子不同(除非你是红绿色盲,在这种情况下可能很难看到,我的道歉)。

http://jsfiddle.net/9gBfX/

是什么给出了?


注意:

  • 您可以将系统时区设置为EST / EDT,以便在我看到它时查看jsfiddle示例。
  • 日期的月份数为零; 11不是拼写错误。
  • 此问题出现在我查看的每一年。

5 个答案:

答案 0 :(得分:6)

查看V8's source code后:

// Specification:
// Accept ES5 ISO 8601 date-time-strings or legacy dates compatible
// with Safari.
<...>
//  A string that matches both formats (e.g. 1970-01-01) will be
//  parsed as an ES5 date-time string - which means it will default
//  to UTC time-zone. That's unavoidable if following the ES5
//  specification.

读取周围的代码,似乎长度为月和日2符号的日期时间字符串被视为有效的ES5日期时间字符串。在ES5解析器中,在解析日期和时间之后,还有一个注释:

// Successfully parsed ES5 Date Time String. Default to UTC if no TZ given.

对于“YYYY-MM-DD”,一旦代码到达那么远,ES5解析器已成功解析整个字符串,因此它在遗留解析器有机会本地化时区之前返回。否则(月/日是一个符号长)它被视为“遗留”日期时间,遗留解析器可以处理它并进行本地化。

答案 1 :(得分:3)

这是从其他答案中得出的简化答案。

日期识别不同的字符串格式

  • 非标准日期
  • RFC 2282日期
  • ES 5个日期

大多数格式都被解释为本地日期

RFC 2282的第14页,我们看到:

  

日期和时间应该以当地时间表示。

非标准日期的处理方式类似。

ES 5格式被解释为UTC

在ES 5规范的section 15.9.1.15中,我们看到:

  

缺席时区偏移的值为“Z”。

&#34; Z&#34;表示UTC时间。

十月十日

ES 5格式的日期需要两位数的月份和日期。原帖中的月份和日期不是零填充。 &#34; 2020年9月9日&#34;不是有效的ES 5日期表示;它是一种非标准格式,因此在当地时间进行解释。 &#34;二零二零年十月一十日&#34; 是有效的ES 5日期表示,因此必须以UTC格式解释。

可能的解决方法

  • 不要使用字符串构造函数/ Date.parse!
  • 更改分隔符,使格式永远不会与ES 5格式匹配。
  • 指定时区。
  • 将日期调整为当地时间。如果他们有几小时或几分钟:date.setMinutes(date.getTimezoneOffset());(这似乎无论如何都有效。)

答案 2 :(得分:2)

使用“ - ”作为美国日期的日期分隔符会混淆某些浏览器,有些会执行日期算术,其他浏览器将返回NaN,因此请使用“/”日期分隔符。文化感知解决方案是使用date.js,这是一个出色的JavaScript日期处理程序,可以解决您指出的问题(http://www.datejs.com/)。使用parse方法可以消除所有混淆:

Date.parse("2020-12-15").toString() // yields the correct date ("Tue Dec 15 00:00:00 PST 2020"). 

答案 3 :(得分:2)

this post上转发,由于浏览器的各种Date实现,Date.parse()的字符串参数构造函数似乎是实现敏感的。

您的测量结果是正确的,如果您希望浏览器正确解析EST,您可能应该完全避免使用此构造函数。

答案 4 :(得分:2)

看起来日期构造函数需要空格而不是“ - ”。它是推荐的方式。看看这个链接:
3.3. Date and Time Specification

  

虽然在整个日期时间内允许折叠白色空间   规范,建议使用单个空间   FWS出现的每个地方(无论是必需的还是可选的)

另请查看此链接:
https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date

  

dateString:表示日期的字符串值。字符串应该在一个   解析方法识别的格式(符合IETF的RFC 2822   时间戳)。

我尝试了以下代码并返回true

dateFromNumbers = new Date(2020, 11, 15);
dateFromString = new Date("2020 12 15");
alert(+dateFromNumbers == +dateFromString);​

从十月开始,这也不是一个问题,它与两位数的月份有关。如果我在9月尝试相同的方法:

dateFromNumbers = new Date(2020, 8, 15);
dateFromString = new Date("2020-09-15");
alert(+dateFromNumbers == +dateFromString);​ // This returns false

但如果我在9月份使用单个数字,则返回true

dateFromNumbers = new Date(2020, 8, 15);
dateFromString = new Date("2020-9-15");
alert(+dateFromNumbers == +dateFromString);​ // This returns true

如果使用九位数的空格,则返回true

dateFromNumbers = new Date(2020, 8, 15);
dateFromString = new Date("2020 09 15");
alert(+dateFromNumbers == +dateFromString);​//This returns true