18

首先,我认为时区可能与此有关。我在美国东部时间/美国东部时间。另外,我正在 chromium 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)

看起来dateFromStringdateFromNumbers这种情况早 5 小时(EST 是 GMT - 5,我确信它以某种方式相关)。

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

http://jsfiddle.net/9gBfX/

是什么赋予了?


笔记:

  • 您可以将系统时区设置为 EST/EDT 以查看我所看到的 jsfiddle 示例。
  • 日期的月份数字是从零开始的;这11不是错字。
  • 这个问题出现在我检查的每一年。
4

5 回答 5

6

查看V8 的源代码后:

// 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 解析器就成功地解析了整个字符串,所以它在遗留解析器有机会本地化时区之前返回。否则(月/日是一个符号长),它将被视为“遗留”日期时间,遗留解析器会处理它并对其进行本地化。

于 2012-04-22T17:06:24.350 回答
3

这是其他答案的简化答案。

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

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

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

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

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

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

ES 5 格式被解释为 UTC

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

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

“Z”代表 UTC 时间。

十月十号

ES 5 格式的日期需要两位数的月份和日期。原始帖子中的月份和日期不是零填充的。“2020-9-9”不是有效的 ES 5 日期表示;它是一种非标准格式,因此以本地时间进行解释。“2020-10-10”有效的 ES 5 日期表示,因此必须以 UTC 解释。

可能的解决方法

  • 不要使用字符串构造函数/Date.parse!
  • 更改分隔符,使格式永远不会匹配 ES 5 格式。
  • 指定时区。
  • 将日期调整为当地时间。如果他们有几个小时或几分钟:(date.setMinutes(date.getTimezoneOffset());无论如何,这似乎有效)。
于 2012-04-22T17:55:21.473 回答
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"). 
于 2012-04-22T16:21:04.663 回答
2

根据这篇文章,由于浏览器的各种实现,似乎Date的字符串参数构造函数是实现敏感的。Date.parse()

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

于 2012-04-22T16:39:53.060 回答
2

看起来日期构造函数需要空格而不是“-”。它是推荐的方式。看看这个链接:
3.3。日期和时间规范

尽管整个日期时间规范都允许折叠空白,但建议在 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);​

从 10 月份开始也不是问题,它与两位数月份有关。如果我在九月尝试相同的方法,那么:

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
于 2012-04-22T17:08:21.333 回答