Javascript new Date函数中的奇怪行为

时间:2014-01-16 03:42:09

标签: javascript

我试图在javascript中使用字符串制作Date对象,但我看到javascript解析日期字符串在这里很奇怪。

> new Date("2012-01-01");
Sun Jan 01 2012 07:00:00 GMT+0700 (ICT)

> new Date("01-01-2012");
Sun Jan 01 2012 00:00:00 GMT+0700 (ICT)

> new Date("2012-01-01") == new Date("01-01-2012")
false

我使用Chrome 32,因为你可以看到它们有7个小时不同。请告诉我这里发生了什么?

2 个答案:

答案 0 :(得分:16)

关于浏览器如何实现Date.parsespec)的全部内容。在传递给Date构造函数(spec)的字符串上调用该方法,并首先尝试将字符串与已知格式匹配,以确定哪些值在哪里。我希望不同的浏览器以稍微不同的方式实现该决策树,但Chrome的实现可能假定"2012-01-01"版本是ISO-8601标准的前缀,该标准基于Zulu或GMT / UTC,并且包含时区("2012-01-01T00:00:00Z-07:00"),而"01-01-2012"版本是基于您的LOCAL时区的本地化,并且不打算指定它("01-01-2012 00:00:00")所以7小时差异是基于ISO标准日期和本地化日期之间的7小时偏移。相反,Date.prototype.toString()spec)应该显示本地时间并由Date构造函数返回,这就是为什么它在测试的两个返回值中都已本地化。

来自Date.parse的{​​{3}}:

  

该函数首先尝试根据日期时间字符串格式(spec)中调出的规则来解析字符串的格式。如果String不符合该格式,则该函数可以回退到任何特定于实现的启发式或特定于实现的日期格式。无法识别字符串或包含格式为String的非法元素值的日期将导致Date.parse返回NaN。

这意味着如果您不使用15.9.1.15中指定的完整ISO-8601日期,浏览器可以随着时间的推移进行补充,或者只是给您NaN。即使这是标准,一些浏览器因为没有实际遵循标准而臭名昭着,所以您可以考虑通过自己解析数据并使用另一个Date构造函数(15.9.1.15)来明确指定所有参数。

答案 1 :(得分:3)

其他答案解释了造成差异的原因。避免此问题的一个好方法是解析字符串yoruself。如果您希望2012-01-01被视为UTC,那么:

function dateFromUTCString(s) {
  var s = s.split(/\D/);
  return new Date(Date.UTC(s[0], --s[1], s[2]));
}

如果您想将其视为本地日期,则:

function dateFromString(s) {
  var s = s.split(/\D/);
  return new Date(s[0], --s[1], s[2]);
}