moment.js-UTC输入错误的日期


93

为什么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”,为什么它返回的是第17位而不是第18位。

但是,如果我在不使用utc的情况下使用momentjs:

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

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

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


4
我认为您不需要toString()之后format()(它已经返回了一个字符串)。
亚历克斯

Answers:


157

默认情况下,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"

或者,正如Matt Johnson在他的回答中提到的那样,您可以(并且应该应该)首先将其解析为UTC日期,并使用moment.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"

非常感谢。因此,基本上,我应该始终在使用UTC时及时传递或像在第二种方法中那样传递UTC。
brg

要么坚持当地的时区。如果从服务器发送时间,则可以将它们表示为Unix时间戳(X)或特定时区的字符串。无论如何,为什么要使用UTC而不是用户的本地时区(除了将标准化数据发送到服务器的目的)?
MasterAM

1
请注意new Date('07-18-2013 UTC'),如果您愿意的话,在IE8中将无法使用。
Dzmitry Lazerka

2
我已经为此苦苦了很长时间。他们确实应该在他们的网站上对此做很好的解释,因为我认为这是moment.js的最常见用例。非常感谢!你真的救了我的皮肤!
WebWanderer '16

该代码对我有用:[code] moment(strDate,'DD / MM / YYYY h:mm A')。utc(strDate).format(“ YYYY-MM-DD HH:mm”)[/ code]
奥马尔Isaid '18

36

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

以您提供的格式将输入时刻解析为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日处理,具体取决于浏览器的区域性设置。


仅出于学习目的,在控制台中:moment.utc('2013-07-18 0:00 +0100','YYYY-MM-DD HH:mm')给我“ 2013-07-18 0:00 +0100 “但是在运行时对jsfiddle的关注不同的是:2013年7月25日,星期四,格林尼治标准时间 +0100,请注意01:00:00。谢谢。
brg

moment在控制台上输出原始文件不是很有用。您可能正在查看其内部属性之一。您应该先格式化它,然后再检查结果。例如moment.utc().format()moment().format()
马特·约翰逊

默认情况下,日期和时刻都会在浏览器的本地时区中解析输入字符串。我现在正在使用EDT。new Date('2010-12-12')给我Date {Sat Dec 11 2010 19:00:00 GMT-0500 (Eastern Daylight Time)}FF 38.0.5。只是为了使“当地时间”的含义具体化,在这种情况下,这似乎意味着Date将假设一个无时区的字符串位于UTC中,并将解析为当地时间。” d.getUTCDate()= 12d.getDate()=11
鲁芬2015年

1
是的,有一些例外。ES5(当前最新的浏览器)会将带连字符的日期解释为UTC,但是几乎所有其他内容都被解释为本地时间。ES6正在更改此行为,以将同一字符串解释为本地时间。我更新了答案。
马特·约翰逊

哈,是的,只是在MDN遇到了这个问题(确切地说'2012-12-12'是UTC b / c,它是ISO格式,但是'December 12, 2012'甚至'2012/12/12'在ES5中用本地时区进行了解析),但是您已经击败了我。ES6如此出色,以至于它们全都本地化了(他讽刺地说)。日期令人痛苦,(c)日期的到来
鲁芬(Ruffin
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.