【问题标题】:Chrome JavaScript Engine Date Parsing Defaults to Year 2001 [duplicate]Chrome JavaScript 引擎日期解析默认为 2001 年 [重复]
【发布时间】:2021-01-10 19:52:05
【问题描述】:

在 Chrome 中,当字符串不包含年份时,为什么 JavaScript 默认为 2001?

t = new Date('Monday, Jan 11')

Thu Jan 11 2001 00:00:00 GMT+0000 (Greenwich Mean Time)

编辑: fwiw,这种行为也出现在 React Native 中

【问题讨论】:

  • 它似乎是特定于 Chrome 的。 Firefox 返回无效日期
  • 这是一种非标准的日期格式。因此,结果完全取决于实现——允许引擎使用任何解析模式或启发式方法来确定日期。我建议要么使用标准日期格式,它是 ISO 8601 的精简版,要么使用日期库来解析日期。
  • 简短的回答是,以 ECMA-262 支持的格式以外的格式解析时间戳是依赖于实现的。您可能会得到预期日期、其他日期或无效日期,其中相同的字符串在不同的实现(甚至相同实现的版本)中产生不同的结果。因此强烈建议避免使用内置解析器。
  • 谢谢大家的回答!同意这是浏览器特定的错误。 @RobG 你能重新打开这个问题吗?这与另一个问题并不完全相同。我希望了解 v8 中关于这个特定问题的实现。谢谢!

标签: javascript date


【解决方案1】:

我发现这是一个有趣的问题,所以我深入研究了 V8 引擎 的源代码,Chromium 和 Chrome 使用的 javascript 引擎(出现这种现象的浏览器)对这种奇怪的行为进行逆向工程。

我在dateparser.h找到了这个sn-p:

if (!is_iso_date_) {
  if (Between(year, 0, 49))
    year += 2000;
  else if (Between(year, 50, 99))
    year += 1900;
}

假设没有年份的日期不符合 ISO 标准,20001900 将添加到 OP 未定义 year。这应该表明50上方有一个断点,事实证明这是真的:

// Tested in Chrome:
console.log(new Date('1 1 49').getFullYear()); // 2049
console.log(new Date('1 1 50').getFullYear()); // 1950

文件year 的上层定义如下:

int year = 0; // Default year is 0 (=> 2000) for KJS compatibility.

KJS 是一个非常早期的 javascript 引擎,被 WebKit 采用,后者又被分叉到 Chromium,所以这个默认值似乎是出于与古代祖先引擎的未知兼容性原因而选择的。不过按照这个逻辑,年份应该默认为2000,而不是2001。原来这可能是故意的。

在同一个文档中,出现了这个sn-p:

// Day and month defaults to 1.
while (index_ < kSize) {
  comp_[index_++] = 1;
}

comp_ 保存[day, month, year] 的默认值。从评论来看,kSize 应该是 3,所以如果没有另外指定,只有 daymonth 会被设置为 1

但是,kSize4,因此循环也会遍历 year 部分。然后year(如果未指定)设置为1,覆盖之前的int year = 0 语句。前面提到的条件启动,year += 2000 发生,你最终得到了 2001 的奇数默认值。

我怀疑这是一个错误,但无法确定解析不存在日期的预期行为很难定义。无论如何,您应该最好指定自己的默认年份。至此,通过遥远的 V8 引擎源代码进行的小小的推测之旅结束。

【讨论】:

    【解决方案2】:

    如果传递一个字符串,则 Date 的构造函数使用 Date.parse(),其中:

    摘录:

    ECMAScript 规范规定:如果字符串不符合标准格式,则函数可能会退回到任何特定于实现的启发式算法或特定于实现的解析算法。无法识别的字符串或包含 ISO 格式字符串中非法元素值的日期应导致 Date.parse() 返回 NaN。

    但是,日期字符串中的无效值不被识别为 ECMA-262 定义的简化 ISO 格式可能会也可能不会导致 NaN,具体取决于浏览器和提供的值,例如:

    // Non-ISO string with invalid date values
    new Date('23/25/2014');
    

    在 Firefox 30 中将被视为 2015 年 11 月 25 日的本地日期,而在 Safari 7 中将被视为无效日期。

    所以答案是一个组合,因为你执行的浏览器决定了它,而且它不是一个标准,所以浏览器可能会返回任何东西。

    【讨论】:

      【解决方案3】:

      这是由您的浏览器完成的,您可能正在使用 Crome。使用其他浏览器也可以获取 Invalid Date。

      【讨论】:

      • OP 没有得到无效的日期,他们得到了一个意想不到的年份(2001 年)。 Safari 返回一个日期为 2000 年,Chrome 返回一个 2001 年,而 Firefox 返回一个无效的日期。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-12-25
      • 2021-04-12
      • 1970-01-01
      相关资源
      最近更新 更多