新日期无法解析“31”,但无法解析“32”

Jon*_* M. 2 javascript date

我正在使用 Date 尝试从 2 位数年份中获取完整的年份,我注意到一些不一致之处:

$ new Date("12")
Sat Dec 01 2001 00:00:00 GMT+0000 (GMT)
$ new Date("13")
Invalid Date
$ new Date("31")
Invalid Date
$ new Date("32")
Thu Jan 01 2032 00:00:00 GMT+0000 (GMT)
$ new Date("99")
Fri Jan 01 1999 00:00:00 GMT+0000 (GMT)
$ new Date("999")
Tue Jan 01  999 00:00:00 GMT+0000 (GMT)
Run Code Online (Sandbox Code Playgroud)

对这种废话有任何合理的解释。

OSX 上的浏览​​器是 Chrome

T.J*_*der 5

由于所有这些都不符合规范,Chrome 可以依靠自己的启发式方法。这是一个很好的例子,说明了为什么最好避免依赖未指定的行为。

new Date(string)就像解析字符串一样Date.parse(string)规范是这样说的:

该函数首先尝试根据日期时间字符串格式( 20.3.1.16 )中调用的规则(包括扩展年份)解析字符串的格式。如果字符串不符合该格式,则该函数可能会回退到任何特定于实现的启发法或特定于实现的日期格式。

所以,再一次,如果我们喂它"32"或类似的东西,我们就超出了规格。

那么 Chrome 在做什么呢?或者更准确地说,V8 在做什么?为此,我们必须点击源代码,我在其中找到了这个方便的评论:

后跟“:”的无符号数字是时间值 [snip]... 任何其他数字都是日期组件并添加到 DayComposer。

例如,如果可能的话,它将采取"12"and "31"and such 并尝试找出它们是日期的哪一部分。这样做时,如果值 < 13,它似乎会尝试匹配月份,放弃 13-31(例如,可能是日值),而高于该值则匹配年份。

从你的例子中可以清楚地看出:

$ new Date("12")
Sat Dec 01 2001 00:00:00 GMT+0000 (GMT)
Run Code Online (Sandbox Code Playgroud)

它决定 12 是一个月,并将年份默认为 2001 年。

$ new Date("13")
Invalid Date
$ new Date("31")
Invalid Date
Run Code Online (Sandbox Code Playgroud)

在这个范围内,它无法弄清楚它是什么。

$ new Date("32")
Thu Jan 01 2032 00:00:00 GMT+0000 (GMT)
Run Code Online (Sandbox Code Playgroud)

我们已经过了可能是一天的时间点,所以在本世纪它会持续很多年。

$ new Date("99")
Fri Jan 01 1999 00:00:00 GMT+0000 (GMT)
Run Code Online (Sandbox Code Playgroud)

上个世纪的岁月;在两位数年份处理中相当常见,范围默认为 1900 秒,其余部分默认为 2000 秒。

$ new Date("999")
Tue Jan 01  999 00:00:00 GMT+0000 (GMT)
Run Code Online (Sandbox Code Playgroud)

三位数,必须是年份,不需要推断世纪。

这个故事的寓意是:坚持指定的输入格式,或者自己解析日期。:-)

  • 非常好的答案。去投票吧。我删除了我的,因为显然是不正确的 (3认同)