JavaScript日期对象构建错误的日期

JavaScript Date object building wrong date

本文关键字:日期 错误 对象 JavaScript 构建      更新时间:2023-09-26

我有一个问题,即JavaScript日期对象被不正确地构建。我不知道如何最好地解决这个问题。这就是我正在做的:

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

。我知道十一月没有31天。这是故意的事故。问题是这个日期不是简单地没有建立起来,而是实际上建立在12月1日??

现在我认为这可能是一个地区问题,当尝试相同的JSFiddle(或StackOverflow片段如下),我得到10月31日?

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

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

问题不是这个日期简单地没有构建,它实际上构建为12月1日??

现在我认为这可能是一个区域问题…

不,这是设计特点。Date被明确设计用于处理日期之间的滚动(在这种情况下,我认为这可能归结为抽象的DateFromTime操作),这就是为什么像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');

注释: ES5规范中有一个错误,将new Date("2016-08-01")的行为定义为将字符串解释为UTC,这违反了ISO-8601标准,认为它应该解释为"本地时间";因为没有时区指示符。这个规范错误在ES2015中得到了修复,但不幸的是,一段时间以来,仍有浏览器(尤其是Firefox)继续使用ES5版本。我刚刚测试了最近的Chrome和Firefox,它们现在都遵循ES2015标准,但要注意这一点。如果您的代码有可能在浏览器上运行,实现不正确的行为,请在字符串末尾添加标准+/-HH:MM格式的时区指示器(或添加"Z"并使用UTC函数[getUTCFullYear等]而不是上面的本地时间函数[getFullYear等])。

这可能被认为是一个bug在任何正在使用的实现(Chrome?)。根据ECMA-262:

不可识别的字符串或在字符串格式中包含非法元素值的日期将导致Date。解析返回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. js)解析字符串。Parse(它们等价于解析),因为不同实现之间的解析差异很大。