JavaScript Date对象构建错误的日期

时间:2016-10-29 12:04:29

标签: javascript date locale

我有一个问题,即JavaScript Date对象的构建不正确。我不确定如何最好地解决这个问题。这就是我正在做的事情:

var date = new Date('2016-11-31');

现在。据我所知,11月没有31天。这是一个意外的事故。问题是这个日期根本没有构建,它实际上构建为12月1日??

现在我认为这可能是一个区域设置问题,因为在JSFiddle(或下面的StackOverflow片段)中尝试相同时,我得到10月31日?



var date = new Date('2016-11-31');
console.log(date);




有谁知道如何解决这个问题?

2 个答案:

答案 0 :(得分:0)

  

问题在于,而不是这个日期根本无法构建,它实际构建为12月1日??

     

现在我觉得这可能是一个地方问题......

不,这是一个设计特色。 Date明确地设计用于处理日期之间的翻转(在这种情况下,我认为它可能属于抽象DateFromTime operation),这就是myDate.setDate(myDate.getDate() + 1)这样的事情可以可靠地实现的原因用来增加一天,即使从一个月到下一个月。

在评论中,您已经问过,如果日期字符串在您的问题中识别出来的方式无效,那么这种方式是否会失败;我知道的唯一方法是在之后检查结果:

// Note: This example only handles YYYY-MM-DD, not times
function strictCreateDate(str) {
  var date = new Date(str);
  if (isNaN(date.getTime())) {
      throw new Error("Invalid date: '" + str + "'");
  }
  var parts = str.split("-");
  if (+parts[0] != date.getFullYear() ||
      +parts[1] != date.getMonth() + 1 ||
      +parts[2] != date.getDate()) {
      throw new Error("Invalid date: '" + str + "'");
  }
  return date;
}

(如果您希望返回无效的Date个实例,而不是抛出错误,请将上面的第一个throw更改为return date;,将第二个return new Date(NaN);更改为// Note: This example only handles YYYY-MM-DD, not times function strictCreateDate(str) { var date = new Date(str); if (isNaN(date.getTime())) { throw new Error("Invalid date: '" + str + "'"); } var parts = str.split("-"); if (+parts[0] != date.getFullYear() || +parts[1] != date.getMonth() + 1 || +parts[2] != date.getDate()) { throw new Error("Invalid date: '" + str + "'"); } return date; } function test(str) { try { var dt = strictCreateDate(str); console.log(str + " => " + dt.toISOString()); } catch (e) { console.log(str + " => " + e.message); } } test('2016-11-30'); test('2016-11-31'); test('2016-08-01'); }。)

示例:



new Date("2016-08-01")




注意:ES5规范中存在错误,该错误定义了+/-HH:MM将字符串解释为UTC的行为,违反了ISO-8601标准,说它应该被解释作为"当地时间"因为没有时区指标。这个规范错误在ES2015中得到了修复,但遗憾的是有一段时间以来,浏览器(特别是Firefox)延续了ES5版本。我刚刚测试了最近的Chrome和Firefox,它们现在都遵循ES2015标准,但要注意这一点非常重要。如果您的代码有可能在实施错误行为的浏览器上运行,请将标准"Z"格式的时区指示符添加到字符串末尾(或向其添加UTC并使用getUTCFullYear函数[getFullYear等]代替上面的本地时间函数[{{1}}等]。

答案 1 :(得分:0)

这可能被视为正在使用的任何实现中的错误(Chrome?)。根据ECMA-262:

  

无法识别包含格式为String的非法元素值的字符串或日期将导致Date.parse返回NaN。

注意Date必须解析 Date.parse

的字符串

像'2016-11-31'这样的字符串应该被视为ISO 8601,值31对于11月是无效的,因此new Date('2016-11-31')应该返回一个无效的日期(即其时间值设置为NaN的日期) )。这是Safari和Firefox的结果,但不是Chrome。

实施可能决定由于31无效,因此该字符串无效ISO 8601,因此根据以下任何方式解析它:

  

如果String不符合该格式,则该函数可以回退到任何特定于实现的启发式或特定于实现的日期格式。

因此,基本上日期字符串可以以实现所需的任何方式进行解析。

黄金法则是永远不会使用Date构造函数解析字符串(或Date.parse,它们等同于解析),因为实现之间的解析差异很大。