在javascript中获取UTC日期(不是UTC字符串)

新手上路,请多包涵

我想使用 moment 或任何其他可能性获取 utc 日期。 utcString = moment.utc(someDate)).format() 给出的是 utc 字符串而不是 utc 日期。我无法使用它执行 utcString.getDate() 等操作。请帮助我提供 utc 日期对象。

moment.utc(new Date()).toDate() 再次将日期转换为我的当地时间。

例如:我想要像 "2019-10-31T00:00:00.000Z" 这样的 utc 格式的字符串转换为 utc 日期并执行可以使用 Date() 对象执行的操作(如 getDate(), getFullYear() 等)

原文由 qaz2625 qaz 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 474
1 个回答

来自 Date 对象 的 MDN 文档

创建一个 JavaScript Date 实例,以独立于平台的格式表示单个时刻。 Date 对象包含 Number 表示自 1970 年 1 月 1 日 UTC 以来的毫秒数。

换句话说, Date 对象只是一个包含单个值的抽象,并且该值 始终 以 UTC 表示。如果您想查看该值,请调用 .valueOf().getTime() ,或将其强制为数字(例如: +d )。

Date 对象的许多特性可以以不同的方式公开该值,例如以标准化的字符串格式、人类可读的字符串格式或表示部分组件值(即年)的各种其他数字、月、日、时、分、秒、毫秒)。其中一些函数在确定其输出时使用 UTC(例如 .toISOString().getUTCFullYear() 等),而其他函数在确定其输出时使用计算机的本地时区(例如 .toString() , .getFullYear() 等)。

这很容易让人感到困惑,特别是如果调用 console.log 直接在 Date 对象上。需要记住的是,控制台日志记录功能是 _特定于实现的_。您可能会看到一个人类可读的字符串,看起来像本地时间,就好像您调用了 .toString() ,但是一些实现给您一个字符串,看起来像 ISO 格式的 UTC 时间,就好像您调用 .toISOString() .真的,当涉及到日志记录时,实现可以做任何它想做的事。它可以打印出 一只发出嘶嘶声的猫

更令人困惑的是, Date 构造函数根据本地时间获取其数字参数,因此人们可能会认为 new Date(2019,8,5,0,0,0) 是本地时间的 Date 对象,-但实际上它在构造期间转换为 UTC 并记录相应的时间戳。可以通过 new Date(Date.UTC(2019,8,5,0,0,0)) 将这些值解释为 UTC,但是 Date 对象本身 _是 UTC 两种方式_。

关键是,不要因为 看到 当地时间就认为 Date 对象 当地时间。它不是。它从来没有。因此,在 不同 的时区要求它也是不可能的。在 UTC 中请求它是您已经拥有的。

我想要 utc 格式的字符串,如 "2019-10-31T00:00:00.000Z" 转换为 utc 日期并执行操作(如 getDate()getFullYear() 等)-

您不会调用 getDategetFullYear 。这些函数在内部请求计算机的本地时区,并在确定结果之前将其应用于时间戳。相反,您会调用 getUTCDategetUTCFullYear ,它们不适用本地时区。

… 实际上我正在使用 react-date-picker。 … (来自您的评论)

那里有很多日期选择器。如果您没有从您正在使用的那个中获得功能,请尝试另一个。

当谈到时区时,最好的人会做以下两件事之一:

  • 他们可能会为选择器的“模式”提供设置,通常是本地或 UTC,或者可能是特定的 UTC 偏移量或时区 ID。这将允许您预先确定您希望选择器在其输入和输出方面的行为方式。

  • 他们可能只是将输入和输出作为 String 提供,而不是作为 Date 对象。这将允许选择器以中立的方式运行,然后您将以您喜欢的任何方式解释用户的选择。 (顺便说一句,HTML5 的 <input type="date"> 就是这样工作的。)

不幸的是,有很多日期选择器 不是这样 工作的,并且假设您只是想要一个 Date 基于本地时间创建的对象。为了应对这一点,你需要撒一点谎。

例如,假设我从假定我当地时区的日期选择器中选择 2019-09-05 。它在内部执行 new Date(2019, 8, 5) ,或者它可能执行 new Date("2019-09-05T00:00:00.000") 。在 Date 对象记录相应的时间戳值之前,任何一种形式都将被解释为本地时间。但我 实际上并不 想要那样——我希望用户选择一个 UTC 日期。所以我添加了这段代码来调整从选择器返回的对象( d ):

 d.setTime(d.getTime() - (d.getTimezoneOffset() * 60 * 1000));

这种技术称为 _纪元移位_,因为它将时间戳的基础从 1970-01-01T00:00:00.000Z Unix 纪元移开(或移向)。在这种情况下,它是原始的 Date 对象(由选择器创建的对象)创建不正确,因此上述将其移回标准 Unix 纪元。

请记住,此技术是关于让您的用户选择一个基于 UTC 的值,并将其恢复为常规 Date 对象。它 用于让您的用户选择本地值并将其 转换 为 UTC。为此,您 必须 使用为此目的设计的功能( getUTCFullYeargetISOString 等)。

原文由 Matt Johnson-Pint 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题