新日期无法解析为“31”而不是“32”

时间:2017-03-06 18:03:27

标签: 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)

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

浏览器是OSX上的Chrome

2 个答案:

答案 0 :(得分:4)

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

new Date(string)解析字符串就像Date.parse(string)一样。以下是the spec所说的内容:

  

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

因此,如果我们提供"32"或类似内容,我们就会超出规范。

那么Chrome正在做什么?或者更确切地说,V8在做什么?为此,我们必须hit the source,我发现了这个方便的评论:

  

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

。例如,如果可能的话,它将采用"12""31"等并尝试弄清楚它们的日期部分。这样做时,如果值<&lt;&lt; 13,放弃13-31(例如,可能是一天的价值),并且高于此数年。

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

$ new Date("12")
Sat Dec 01 2001 00:00:00 GMT+0000 (GMT)

它决定12个月是一个月,并且拖欠了2001年的那一年。

$ 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)

上个世纪的岁月;在两位数的年份处理中相当普遍,其范围默认为1900s,其余的默认为2000s。

$ new Date("999")
Tue Jan 01  999 00:00:00 GMT+0000 (GMT)

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

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

答案 1 :(得分:1)

来自文档Date

  

由于浏览器差异和不一致性,强烈建议不要使用Date构造函数(和Date.parse,它们是等效的)解析日期字符串。对RFC 2822格式字符串的支持仅限于惯例。对ISO 8601格式的支持不同之处在于,仅日期字符串(例如“1970-01-01”)被视为UTC,而不是本地。

     

字符串应采用Date.parse()方法识别的格式

如果预期UTC,那么应该写

new Date(Date.UTC(31)) //    Invalid Date
new Date(Date.UTC(32)) //    Invalid Date
new Date(Date.UTC(12)) //    Invalid Date
new Date(Date.UTC(13)) //    Invalid Date
new Date(Date.UTC("31")) //Invalid Date
new Date(Date.UTC("32"))  //Invalid Date