为什么不是“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")
,它将使用设置为hours
和minutes
,
否则如2 0.3.1.16所述
如果时区偏移量不存在,则将date时间解释为本地时间。