【问题标题】:Why does JavaScript interprete 1/1/0000 as 1/1/2000?为什么 JavaScript 将 1/1/0000 解释为 1/1/2000?
【发布时间】:2015-08-14 09:49:06
【问题描述】:

我遇到了一些奇怪的行为,虽然我对此并没有真正的问题,但我想知道它背后的原因。

我写了以下语句:

console.log(new Date("0000-1-1"));
console.log(new Date("0000-01-01"));
console.log(new Date("0000-01-01T00:00:00Z"));
console.log(new Date(0, 0, 1));

虽然所有日期“看起来”相似,并且如果您使用正常的日/月/年表现相同,但在这种情况下并非如此。

结果如下:

Sat Jan 01 2000 00:00:00 GMT+0100 (CET)
Sat Jan 01 0 01:00:00 GMT+0100 (CET)
Sat Jan 01 0 01:00:00 GMT+0100 (CET)
Mon Jan 01 1900 00:00:00 GMT+0100 (CET)

这对我来说很有趣。我可以同意最后一个,因为JavaScript spec 清楚地说明了以下内容:

年份

代表年份的整数值。从 0 到 99 的值映射到 1900 到 1999 年。请参见下面的示例。

我也可以理解第二个和第三个结果,因为这取决于RFC 2822。他们确实接受 4*DIGITS 作为一年,所以 0000 应该是 RFC 规范的第 0 年(虽然我没有完全阅读它)。

Date 构造函数之一可用于 1900 年以上的日期,而另一个构造函数允许范围更广 (RFC) 的日期,这有点奇怪。

但是,我不明白第一个结果。 2000年从何而来?我明白这个日期不是一个合适的日期,但它不应该返回Invalid Date 来代替这个日期吗?

【问题讨论】:

  • 我假设你在 Chrome 中测试过它。顶部的new Date("0000-1-1") 在不同的浏览器中有所不同。在 Firefox 中它输出一个无效日期,在 IE 中它输出 Dec 01 1900
  • 正如 A1rPin 所指出的,这似乎是特定于 Chrome 的。这是 V8 日期解析器的代码,可能包含一些线索:github.com/v8/v8-git-mirror/blob/master/src/dateparser-inl.h
  • 啊,是的,对不起,我在 Chrome 中测试过 :) 应该在其他浏览器中测试过。
  • 以毫秒为单位的日期可用于一致性new Date(-621672192e5),或new Date("0000"),至少4位数年份

标签: javascript date


【解决方案1】:

这是特定于浏览器的。

这是 JavaScript 和浏览器不一致会导致额外的程序员痛苦的另一个领域。一些浏览器会将所有两位数年份解释为 19xx,因此new Date('1/1/49') 给出 1949 年 1 月 1 日,new Date('1/1/50') 给出 1950 年 1 月 1 日。其他浏览器使用 1950 作为“两位数年份截止日期”,所以 new Date('1/1/49') 给出一月1st, 2049 和 new Date('1/1/50') 给出 1950 年 1 月 1 日。

——Two Digit Years in JavaScript - Chris Bristol

您必须记住,您引用的 RFC 文档是在 2001 年 4 月发布的。1900 年代刚刚结束。我猜想为了使日期远离 1900 年代的现代化,一些浏览器现在将 0 到 49 映射为 2000 到 2049。然而,50 仍然被映射为 1950。

上面引用的文章还继续给出了一些测试结果:

以下是结果的简要总结:

  • IE9:未找到两位数的年份截止值。 00 年 = 1900。
  • Chrome 24.0:两位数年份在 49 和 50 之间变化。年份 00 = 2000。
  • Opera:未找到两位数的年份截止值。 00 年 = 1900。
  • Firefox:未找到两位数的年份截止值。 00 年 = 1900。
  • Safari:两位数的年份在 49 和 50 之间变化。年份 00 = 2000。

这篇文章现在已经过时了,所以我想上面的 Opera 和 Firefox 的数据可能已经改变了。

【讨论】:

  • 如果你想避免像这样的浏览器特定的日期,你应该使用像 Moment.js 这样的库,而不是依赖浏览器的 Date 类来做正确的事情。
  • @Simba 是的,我们不会使用它。我只是注意到它,因为在我们的旧数据库系统中,0000-01-01 实际上是日期的NUL 值。但是我们忘了处理这个问题,所以现在我们有一个带有0000-01-01 的jQuery UI 日期选择器,我们注意到通过在其中输入0000-1-1,它会将日期选择器设置为2000,所以我开始玩弄。
  • 无论如何,刚刚在 Mac 上进行了测试,Firefox 和 Safari 都返回 Invalid Date。 Opera 现在与 Chrome 使用相同的引擎,因此它们具有相同的结果。在我的虚拟机上,IE10 显示 1900,但第二个和第三个选项有问题,第二个选项显示 1900,第三个选项显示 NaN。感谢您清除它!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-30
  • 1970-01-01
  • 2011-03-11
  • 2011-12-04
  • 2014-11-11
相关资源
最近更新 更多