moment.js - UTC 给出错误的日期

IT技术 javascript datetime timezone momentjs
2021-02-03 07:00:28

为什么moment.js UTC 总是显示错误的日期。例如来自 chrome 的开发者控制台:

moment(('07-18-2013')).utc().format("YYYY-MM-DD").toString()
// or
moment.utc(new Date('07-18-2013')).format("YYYY-MM-DD").toString()

他们都将返回"2013-07-17"为什么它返回17th而不是18th,这是传入的。

但是如果我使用没有 utc 的 momentjs:

moment(new Date('07-18-2013')).format("YYYY-MM-DD").toString()

我返回“2013-07-18”,这也是我在使用 moment.js UTC 时所期望的。

这是否意味着我们在使用 moment.js UTC 时无法获得正确的日期?

3个回答

默认情况下,MomentJS 在本地时间解析。如果仅提供日期字符串(没有时间),则时间默认为午夜。

在您的代码中,您创建一个本地日期,然后将其转换为 UTC 时区(实际上,它使时刻实例切换到UTC 模式),因此在格式化时,它会向前移动(取决于您的本地时间)或向后。

如果本地时区是 UTC+N(N 是一个正数),并且您解析一个仅限日期的字符串,您将获得上一个日期。

以下是一些示例来说明它(我的本地时间偏移量在 DST 期间为 UTC+3):

>>> moment('07-18-2013', 'MM-DD-YYYY').utc().format("YYYY-MM-DD HH:mm")
"2013-07-17 21:00"
>>> moment('07-18-2013 12:00', 'MM-DD-YYYY HH:mm').utc().format("YYYY-MM-DD HH:mm")
"2013-07-18 09:00"
>>> Date()
"Thu Jul 25 2013 14:28:45 GMT+0300 (Jerusalem Daylight Time)"

如果您希望将日期时间字符串解释为 UTC,您应该明确说明它:

>>> moment(new Date('07-18-2013 UTC')).utc().format("YYYY-MM-DD HH:mm")
"2013-07-18 00:00"

或者,正如马特约翰逊在他的回答中提到的那样,您可以(并且可能应该)首先使用moment.utc()格式字符串作为第二个参数将其解析为 UTC 日期,以防止歧义。

>>> moment.utc('07-18-2013', 'MM-DD-YYYY').format("YYYY-MM-DD HH:mm")
"2013-07-18 00:00"

要反过来将 UTC 日期转换为本地日期,您可以使用该local()方法,如下所示:

>>> moment.utc('07-18-2013', 'MM-DD-YYYY').local().format("YYYY-MM-DD HH:mm")
"2013-07-18 03:00"
我一直在为此苦苦挣扎。他们真的应该在他们的网站上很好地解释这一点,因为我认为这是 moment.js 最常见的用例。太感谢了!你真的救了我的皮肤!
2021-03-27 07:00:28
要么坚持当地时区。如果您从服务器发送时间,您可以将它们表示为 Unix 时间戳 (X) 或特定时区的字符串。无论如何,为什么要使用 UTC 而不是用户的本地时区(除了向服务器发送规范化数据的目的)?
2021-03-29 07:00:28
非常感谢。所以基本上,我应该总是在使用 UTC 时传递时间,或者像在您的第二种方法中那样传递 UTC。
2021-04-03 07:00:28
这段代码对我有用:[code] moment(strDate, 'DD/MM/YYYY h:mm A').utc(strDate).format("YYYY-MM-DD HH:mm") [/code]
2021-04-07 07:00:28
请注意new Date('07-18-2013 UTC'),如果您在意,它在 IE8 中将不起作用。
2021-04-11 07:00:28

双方Datemoment会在解析默认浏览器的本地时区输入字符串。然而Date有时与这方面不一致。如果字符串是特定的YYYY-MM-DD,使用连字符,或者如果是YYYY-MM-DD HH:mm:ss,它会将其解释为本地时间Date,moment将始终保持一致的解析方式。

以您提供的格式将输入时刻解析为 UTC 的正确方法如下:

moment.utc('07-18-2013', 'MM-DD-YYYY')

请参阅此文档

如果您想为输出设置不同的格式,您可以这样做:

moment.utc('07-18-2013', 'MM-DD-YYYY').format('YYYY-MM-DD')

您不需要toString显式调用

请注意,提供输入格式非常重要。没有它,像这样的日期01-04-2013可能会被处理为 1 月 4 日或 4 月 1 日,具体取决于浏览器的文化设置。

Date 和 moment 都会默认解析浏览器本地时区的输入字符串。我现在在 EDT。在 FF 38.0.5 中new Date('2010-12-12')给我Date {Sat Dec 11 2010 19:00:00 GMT-0500 (Eastern Daylight Time)}只是为了将“在当地时间”的含义具体化——在这种情况下,它似乎意味着Date将假定无时区字符串采用 UTC 格式,并将解析为当地时间。” d.getUTCDate()=12d.getDate()=11
2021-03-28 07:00:28
moment在控制台上输出原始数据并不是很有用。您可能正在查看其内部属性之一。您应该在检查结果之前对其进行格式化。例如moment.utc().format()moment().format()
2021-03-30 07:00:28
是的,有一些例外。ES5(大多数当前浏览器)会将带连字符的日期解释为 UTC,但几乎所有其他内容都被解释为本地时间。ES6 正在改变这种行为以解释与本地时间相同的字符串。我更新了答案。
2021-04-02 07:00:28
只是为了学习,在控制台中:moment.utc('2013-07-18 0:00 +0100', 'YYYY-MM-DD HH:mm')给我“2013-07-18 0:00 +0100 "但是当运行时 jsfiddle 的显示不同的是:Thu Jul 25 2013 01:00:00 GMT+0100注意01:00:00谢谢。
2021-04-04 07:00:28
哈,是的,刚刚在 MDN 上遇到了这个问题'2012-12-12'UTC b/c 是 ISO 格式,但'December 12, 2012'甚至'2012/12/12'在 ES5 中用本地时区解析),但你已经打败了我。太棒了,ES6 使它们都成为本地化的 [他讽刺地说]。日期是一种痛苦,(c) 日期的出现
2021-04-05 07:00:28

用这个 :

return moment.utc(new Date(oData.CreatedAtUtc), 'MM/DD/YYYY h:mm A').local().format("YYYY-MM-DD HH:mm") + ' (' + timezoneAbbr + ')';