为什么不是“2016-02-16”等于“2016-02-16 00:00”?

我试图将两个datestring传递给new Date(t)

我希望两个string代表同一时间,毕竟,如果我省略了时间,难道不是当天的午夜吗?

但同时,

 new Date("2016-02-16 00:00") 

回报2016-02-16,午夜,当地时间如预期,

 new Date("2016-02-16") 

返回2016-02-16,午夜UTC,这是错误的,或者至less不是我期望给予另一个string分析的东西。

我会理解,如果他们都有相同的行为,不pipe是按照当地时间还是以UTC来回报,但是为什么他们返回不同的东西似乎是非常不一致的。

作为一个解决方法,每当我遇到一个没有相应时间戳的date,我可以附加“00:00”来获得一致的行为,但似乎这是相当脆弱的。

我从一个INPUT元素中获取了这个值,types为'datetime-local',所以看起来特别不一致,我必须解决页面元素返回的值。

我做错了什么,还是应该做一些不同的事情?

这就是ES5.1规范要做的事情:

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

它还说:

函数首先尝试根据date时间string格式(15.9.1.15)中调出的规则来parsingstring的格式。 如果string不符合该格式,该函数可能会回退到任何特定于实现的启发式或实现特定的date格式。

由于该格式需要date和时间之间的T分隔符,因此有效时间为UTC:

 > new Date("2016-02-16T00:00:00") Tue Feb 16 2016 01:00:00 GMT+0100 (CET) > new Date("2016-02-16") Tue Feb 16 2016 01:00:00 GMT+0100 (CET) 

…而在node.js中,一个无效的时间(没有T分隔符)似乎去执行特定的本地时间:

 > new Date("2016-02-16 00:00:00") Tue Feb 16 2016 00:00:00 GMT+0100 (CET) 

请注意,ES6 改变了这一点,在文档的相同部分更改为:

如果时区偏移量不存在,则将date时间解释为本地时间。

打破变化的喜悦。

编辑

根据TC39的规定,这个规范意味着被解释为没有时区的date和时间string(例如“2016-02-16T00:00:00”)被视为本地(按照ISO 8601),但是仅仅是string(例如“2016-02-16”)作为UTC(与ISO 8601不一致)。

根据规格 :

函数首先尝试根据date时间string格式(15.9.1.15)中调出的规则来parsingstring的格式。 如果string不符合该格式,该函数可能会回退到任何特定于实现的启发式或实现特定的date格式。

date时间string格式接受2016-02-16作为有效date

此格式包含仅限date的表单:

YYYY
YYYY-MM
YYYY-MM-DD

[…]如果不存在HH,mm或ss字段,则使用“00”作为值,缺席sss字段的值为“000”。 缺席时区偏移的值是“Z”。

因此2016-02-16翻译成2016-02-16T00:00:00.000Z

其他date2016-02-16 00:00不符合格式,因此它的parsing是特定于实现。 显然,这样的date被视为具有本地时区,您的示例date将根据时区返回不同的值:

 /* tz = +05:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-15T19:00:00.000Z /* tz = -08:00 */ new Date("2016-02-16 00:00").toISOString() // 2016-02-16T08:00:00.000Z 

概要:

  • 对于符合date时间格式的行为已经很好的定义了 – 在没有时区偏移的情况下,datestring被视为UTC(ES5)或本地(ES6)。
  • 对于不符合的date时间格式,行为是特定于实现的 – 在没有时区偏移的情况下, 通常的行为是将date视为本地。
  • 事实上,实现可以select返回NaN而不是试图parsing不符合的date。 只需在Internet Explorer 11中testing您的代码;)

您可能遇到了ES5,ES6实现和您的预期结果之间的差异。 在MDN的每Date.parse “,特别是跨不同的ECMAScript实现,像”2015-10-12 12:00:00“的string可能被parsing为NaN,UTC或本地时区”是重要的。

在Firefox 44和IE 11中进行的其他testing显示,它们都返回一个new Date("2016-02-16 00:00")的date对象,该对象在试图获取date分量值时返回NaN,而其toString值为“无效date“(不是”NaN“)。 因此追加“00:00获得一致的行为”可以很容易地在不同的浏览器中打破。

正如在其他答案中指出的那样, new Date("2016-02-16")默认使用零时区偏移量,生成午夜UTC而不是本地。

Chrome的V8源代码的每DateParser::Parse()

ES5 ISO 8601date:

[('-'|'+')yy]yyyy[-MM[-DD]][THH:mm[:ss[.sss]][Z|(+|-)hh:mm]]

无符号数字后跟':'是一个时间值,并被添加到TimeComposer中。

如果缺失,时区默认为Z.

 > new Date("2016-02-16 00:00") Tue Feb 16 2016 00:00:00 GMT+0800 (China Standard Time) 

一个匹配两种格式(例如1970-01-01 )的string将被parsing为UTC time-zon – 这意味着它将默认为UTC time-zon e。 如果遵循ES5规范,这是不可避免的。

 > new Date("2016-02-16") Tue Feb 16 2016 08:00:00 GMT+0800 (China Standard Time) 

返回2016-02-16,午夜UTC,这是错误的,或者至less不是我期望给予另一个string分析的东西。

它将时区偏移添加到00:00

new Date("2016-02-16")产出Tue Feb 16 2016 05:30:00 GMT+0530 (India Standard Time)

我的时区是IST,偏移值(分钟) +330 ,所以它增加了330分钟到00:00。

根据ecma-262,第20.3.3.2节Date.parse(string)

如果ToString导致突然完成,则立即返回完成logging。 否则,parsing会将结果string解释为date和时间; 它返回一个数字,与date和时间对应的UTC时间值。 根据string的内容,string可能被解释为本地时间,UTC时间或某个其他时区的时间。

当你明确地设置时间单位new Date("2016-02-16 00:00") ,它将使用设置为hoursminutes

否则如2 0.3.1.16所述

如果时区偏移量不存在,则将date时间解释为本地时间。