【问题标题】:Date('2015-1-1') outputs different from Date(2015-01-01)Date('2015-1-1') 输出不同于 Date(2015-01-01)
【发布时间】:2015-11-29 11:14:47
【问题描述】:

我刚刚发现如果我使用new Date('2015-1-1'),时间是没有时区效果的,但是如果我使用new Date('2015-01-01'),那么在Node.js中时间是有时区效果的。

我输出 4 Date():

    console.log(new Date('2015-1-1'));
    console.log(new Date('2015-01-1'));
    console.log(new Date('2015-1-01'));
    console.log(new Date('2015-01-01'));

输出是

Thu Jan 01 2015 00:00:00 GMT+0800 (CST)
Thu Jan 01 2015 00:00:00 GMT+0800 (CST)
Thu Jan 01 2015 00:00:00 GMT+0800 (CST)
Thu Jan 01 2015 08:00:00 GMT+0800 (CST)

你可以看到最后一次是08:00:00,因为我在+8时区。

我认为输出取决于月份或日期的数字。当它是 10、11 或 12 时,输出总是08:00:00

我想知道为什么以及是否有更好的方法来处理这个问题,除了手动检查月份和日期编号的位?

【问题讨论】:

  • 当我在 Chrome Javascript 控制台上运行您的示例时得到相同的输出,因此它似乎是 V8 错误/功能。
  • 在 Firefox 中,除了最后一行之外,我得到的所有日期都是无效的。另外,我从 MDN 找到了这个:Differences in assumed time zone
  • 解析日期字符串的另一个问题。 唯一 解析日期字符串的可靠方法是手动进行(尽管库可能会对此有所帮助)。前 3 个字符串不完全是 ISO 8601 字符串,因此可以根据实现的需要进行解析。最后一种是 ISO 8601 格式。根据 ECMAScript 2015,它被解析为主机系统的“本地”。在 ES5 下,它必须被解析为 UTC,在此之前(即 ECMAScript ed 3 和更早版本)任何东西,包括 NaN。
  • @RobG 您应该将其发布为答案。 :)

标签: javascript node.js date


【解决方案1】:

直到并包括 ECMA-262 ed 3,日期字符串的解析完全依赖于实现。使用 ES5,没有时区的 ISO 8601 格式字符串将被解析为 UTC,但是解析任何其他类型的日期字符串仍然取决于实现。

在 ECMAScript 2015 中,此类没有时区的字符串将被解析为本地(即,具有基于系统设置的偏移量)。

因此,您的 Node.js 实现似乎无法将前 3 个字符串识别为 ISO 8601,因此根据将它们视为 UTC 的其他一些内部逻辑对其进行解析。

最后一个字符串被视为符合 ISO 8601 标准,因此被解析为本地字符串。

如果您希望将所有此类字符串解析为本地字符串,可以使用如下简单函数:

/*  @param {string} s - date string in format yyyy-[m]m-[d]d
**  @returns {Date} - a Date object for the specified date in a
**  timezone based on system settings.
**  Assumes that the string is a valid date.
*/
function parseISOLocal (s) {
  var b = s.split(/\D/);
  return new Date(b[0], b[1]-1, b[2]);
}

document.write(parseISOLocal('2015-1-1'))

【讨论】:

  • 有了这个函数,我得到了Thu Jan 01 2015 00:00:00 GMT+0800 (CST),没有时区偏移,但默认的 `Date('2015-01-01') 有时区偏移。
  • @BrickYang — 第一个确实有时区偏移 (+08:00)。
【解决方案2】:

可能是一个错误,你能做的最好的就是使用像Moment 这样的库,它似乎没有这个问题:

moment('2015-1-1').toString()
moment('2015-1-01').toString()
moment('2015-01-1').toString()
moment('2015-01-01').toString()

打印:

"Thu Jan 01 2015 00:00:00 GMT+0100"
"Thu Jan 01 2015 00:00:00 GMT+0100"
"Thu Jan 01 2015 00:00:00 GMT+0100"
"Thu Jan 01 2015 00:00:00 GMT+0100"

【讨论】:

  • 并非如此,它只是发生在 moment.js 默认情况下具有某种行为。你还没有解释为什么 OP 会得到他们得到的结果。
  • 不知道为什么,我的回答是指“更好的处理方式”。由于 Moment 在这方面似乎是一致的,而且它还提供了许多不错的功能,这似乎是处理这个问题的好方法。
  • 只有当你告诉它你传递的格式时,Moment才会保持一致,否则它会尝试一系列可能的格式并返回它成功解析的第一个格式的日期。例如,它无法判断 3/2/105 是 2 月 3 日还是 3 月 2 日。但是对于类似 ISO 的格式,它可能是可靠的(但是 2 行函数也可以做同样的事情)。 ;-)
  • 好吧,我想这是所有日期格式的问题(这就是为什么您应该始终使用日期选择器或日期选择器进行此类用户交互的原因)。但正如你所说,这似乎是一种类似 ISO 的格式,所以我猜 yyyy-MM-dd (或多或少)会很好。
猜你喜欢
  • 1970-01-01
  • 2014-01-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
相关资源
最近更新 更多