【问题标题】:Ambiguous behavior of javascript new Date() constructor for same different formatted stringjavascript new Date() 构造函数对于相同的不同格式字符串的模棱两可的行为
【发布时间】:2019-08-22 01:06:32
【问题描述】:

我的本​​地时区是(UTC+06:00) Dhaka。在我自己的时区,我没有发现这个问题。但是在我的电脑中将时区更改为(UTC -12:00) International Date Line West

new Date(["2014","01","01"]) 正在给我输出Wed Jan 01 2014 00:00:00 GMT-1200 (GMT-12:00)

new Date("2014-01-01") 正在给我输出Tue Dec 31 2013 12:00:00 GMT-1200 (GMT-12:00)

为什么会这样? ["2014","01","01"]"2014-01-01" 不应该给出相同的输出吗?

【问题讨论】:

    标签: javascript datetime timezone utc


    【解决方案1】:

    这是由于 new Date("2014-01-01") 是通过 Date 解析创建的,该解析认为此日期为 UTC,然后应用时区,但 new Date(["2014","01","01"]) 被视为时区构造函数中每个参数的文字值。尽管正如下面的 cmets 之一所述,new Date(["2014","01","01"]) 格式不符合 RFC,因此会根据浏览器提供不同的结果。

    来自:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date

    注意:由于浏览器的差异和不一致,强烈建议不要使用 Date 构造函数(和 Date.parse(),其工作方式相同)解析日期字符串。仅按惯例支持 RFC 2822 格式字符串。对 ISO 8601 格式的支持的不同之处在于仅日期字符串(例如“1970-01-01”)被视为 UTC,而不是本地。

    也许您追求的是new Date(Date.UTC(2014,01,01));Date.UTC,以便创建不受用户配置约束的一致日期。

    【讨论】:

    • 所以你说在new Date(["2014","01","01"]),javascript 不应用时区?
    • new Date(["2014","01","01"]) 将在您所在的时区创建一个日期。因此,您看到的结果是:Wed Jan 01 2014 00:00:00 GMT-1200 (GMT-12:00)new Date("2014-01-01")首先创建日期,就好像你在UTC(使用解析)然后'应用'你的时区(-12hs)因此得到你看到的第二个结果:Tue Dec 31 2013 12:00:00 GMT-1200 (GMT-12:00)
    • 感谢您的回答,但关闭时并不完全正确。传入本地时间或输出本地时间时应用时区。传入或输出 UTC 时不会应用它们 - 因为 Date 对象本质上是基于 UTC 的。此外,Date 构造函数或Date.UTC 不接受数组。或者更确切地说,这是规范不允许的,而是特定于实现的行为。看我的回答。
    • 这里与@Shakibuz_Zaman 的问题相关的主要内容是,正如我的回答中提到的,当您传入仅日期字符串时,日期将被视为基于 UTC,而当您使用另一个构造函数分别分配不同的日期部分(年、月、日等),日期实例是根据代码运行的本地时间创建的。
    【解决方案2】:

    一些事情:

    • Date 构造函数不接受数组。请参阅 the specificationthe MDN docs。任何此类津贴都是特定于实施的。例如,new Date(["2014","01","01"]) 将在 Chrome 中工作,因为 Chrome 作者决定允许它,但在 Edge 中它给出了 Invalid Date,因为规范没有要求它。 (同样适用于Date.UTC(array)。)

    • 如果您有单独的日期部分,则应将它们直接传递给构造函数。请注意,在这种形式的构造函数中,月份的范围是 0 到 11,因此您必须从第二个参数中减去一个。

      new Date(2014, 0, 1)
      
    • 1234563浏览器环境中用户的时区,或 Node.js 环境中服务器的时区)。时间参数(小时、分钟、秒、毫秒)默认为0,因此这是本地时区的午夜,或2014-01-01T00:00:00.000
    • 如果您打算传递基于 UTC 的参数,请使用 Date.UTC 函数,并将结果传递回 Date 构造函数,如下所示:

      new Date(Date.UTC(2014, 0, 1))
      

      这会将日期对象设置为 UTC 午夜,或 2014-01-01T00:00:00.000Z

    • 当您将 字符串 传递给日期构造函数时,首先会尝试解析 according to rules defined in the specification。如果规范的规则无法解析它,则可能以特定于实现的方式进行解析。

      规范定义YYYY-MM-DD 格式的字符串(没有任何时间部分)将被解析为UTC。这偏离了 ISO-8601,这就是为什么您在调用 new Date("2014-01-01") 时会看到不同的结果。它被解释为好像您通过了2014-01-01T00:00:00.000Z (UTC)。

    • Date 对象本身只跟踪一个值,即自 Unix 纪元以来的毫秒数,即 1970-01-01T00:00:00.000Z (UTC)。您可以通过调用.valueOf().getTime() 查看此值。因此,当您使用任何被视为本地时间的形式进行解析时,在解析时会发生从本地时间到 UTC 的转换。

    • 稍后,当您执行任何需要本地时间输出的操作时,例如调用.toString(),或使用.getDate().getHours() 等函数时,另一个从基于UTC 的内部时间戳转换为执行当地时间。

    • 1234563在其他情况下,您将看到基于 UTC 的输出,就好像您调用了 .toISOString()。控制台输出是特定于实现的。

    【讨论】:

      【解决方案3】:

      请注意,格林威治标准时间是 -1200。当您指定日期时,我相信它从当天的午夜开始。由于您说的是 2014-01-01,它从当天的午夜减去 12 小时,得到 2013-12-31 下午 12:00。

      【讨论】:

      • 那么为什么 ["2014","01","01"] 没有发生呢?
      猜你喜欢
      • 1970-01-01
      • 2014-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-10-21
      • 1970-01-01
      • 2013-05-05
      相关资源
      最近更新 更多