Chrome JavaScript 引擎日期解析默认为 2001 年

xua*_*uan 2 javascript date

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

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

Thu Jan 11 2001 00:00:00 GMT+0000 (Greenwich Mean Time)
Run Code Online (Sandbox Code Playgroud)

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

soi*_*mon 6

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

我在dateparser.h中找到了这个片段:

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

假设没有年份的日期不符合 ISO 标准,2000或者1900添加到 OP 中 undefined year。这应该表明上面有一个断点50,事实证明这是正确的:

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

文件的高层year定义如下:

int year = 0; // Default year is 0 (=> 2000) for KJS compatibility.
Run Code Online (Sandbox Code Playgroud)

KJS是一个非常早期的 javascript 引擎,被WebKit采用,而 WebKit 又被分叉到 Chromium 中,因此选择这个默认值似乎是出于与古代祖先引擎未知的兼容性原因。但按照这个逻辑,年份应该默认为2000,而不是2001。事实证明这可能就是意图。

在同一文档中,出现以下代码片段:

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

comp_保留 的默认值[day, month, year]。从注释来看,kSize应该3只是这样day,如果没有另外指定,month则将被设置为。1

然而,循环也会迭代该kSize部分。然后(如果未指定)设置为,覆盖之前的语句。发生上述条件后,您最终会得到奇怪的默认值。4yearyear1int year = 0year += 20002001

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