我想使用 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 许可协议
来自
Date
对象 的 MDN 文档:换句话说,
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 中请求它是您已经拥有的。您不会调用
getDate
或getFullYear
。这些函数在内部请求计算机的本地时区,并在确定结果之前将其应用于时间戳。相反,您会调用getUTCDate
或getUTCFullYear
,它们不适用本地时区。那里有很多日期选择器。如果您没有从您正在使用的那个中获得功能,请尝试另一个。
当谈到时区时,最好的人会做以下两件事之一:
他们可能会为选择器的“模式”提供设置,通常是本地或 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
):这种技术称为 _纪元移位_,因为它将时间戳的基础从
1970-01-01T00:00:00.000Z
Unix 纪元移开(或移向)。在这种情况下,它是原始的Date
对象(由选择器创建的对象)创建不正确,因此上述将其移回标准 Unix 纪元。请记住,此技术是关于让您的用户选择一个基于 UTC 的值,并将其恢复为常规
Date
对象。它 不 用于让您的用户选择本地值并将其 转换 为 UTC。为此,您 必须 使用为此目的设计的功能(getUTCFullYear
,getISOString
等)。