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

Javascript moment.js-UTC给出了错误的日期,javascript,datetime,timezone,momentjs,Javascript,Datetime,Timezone,Momentjs,为什么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(

为什么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”,这也是我在使用time.js UTC时所期望的


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

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

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

如果本地时区是UTC+N(N是一个正数),并且您只解析一个日期字符串,那么您将得到上一个日期

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

如果希望将日期时间字符串解释为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('07-18-2013', 'MM-DD-YYYY').format("YYYY-MM-DD HH:mm")
"2013-07-18 00:00"
要反过来将UTC日期转换为本地日期,可以使用以下方法:

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

默认情况下,
日期
时刻
都将解析浏览器本地时区中的输入字符串。然而,
日期
有时与此不一致。如果字符串使用连字符指定为
YYYY-MM-DD
,或者如果字符串为
yyy-MM-DD HH:MM:ss
,则将其解释为本地时间。与
日期
不同,
时刻
的解析方式始终保持一致

按照您提供的格式将输入时刻解析为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日,这取决于浏览器的区域设置。

非常感谢。所以基本上,我应该在使用UTC时总是传递时间,或者像在第二种方法中一样传递UTC。要么这样,要么坚持本地时区。如果从服务器发送时间,可以将其表示为Unix时间戳(X)或特定时区的字符串。不管怎样,为什么要使用UTC而不是用户的本地时区(除了向服务器发送标准化数据的目的)?请注意,
新日期('07-18-2013 UTC')
在IE8中不起作用,如果您介意的话。我已经为此奋斗了很长时间。他们真的应该在他们的网站上很好地解释这一点,因为我假设这是moment.js最常见的用例。非常感谢你!你真的救了我的命!此代码适用于我:[code]矩(strDate,'DD/MM/yyyyy h:MM A')。utc(strDate)。格式(“yyy-MM-DD HH:MM”)[/code]只是为了学习,在控制台中:矩。utc('2013-07-18 0:00+0100','YYYY-MM-DD HH:MM')给我“2013-07-18 0:00+0100”但运行时JSFIDLE上显示的内容不同,即:周四2013年7月25日01:00:00 GMT+0100注意01:00:00。谢谢。在控制台上输出原始
时刻
不是很有用。您可能正在查看它的一个内部属性。您应该在检查结果之前格式化它。例如
矩.utc().format()
矩().format()
。默认情况下,日期和矩都将在浏览器的本地时区解析输入字符串。我现在在美国东部夏令时<代码>新日期('2010-12-12')
提供了FF 38.0.5中的日期{2010年12月11日星期六19:00:00 GMT-0500(东部夏令时)}
。仅将“在本地时间”的含义具体化一下——在本例中,它似乎是指,“
Date
将假定一个无时间分区的字符串以UTC为单位,并将解析为本地时间。”
d.getUTCDate()
=
12
d.getDate()
=
11
是的,存在一些例外。ES5(大多数当前浏览器)将使用连字符将日期解释为UTC,但几乎所有其他内容都解释为本地时间。ES6正在更改此行为,以将同一字符串解释为本地时间。我更新了答案。哈,是的,只是说(
'2012-12-12'
是UTC b/c,它是ISO格式,但是
'2012年12月12日'
甚至
'2012/12/12'
都是用ES5中的本地时区解析的),但你已经击败了我。太棒了,以至于ES6让它们都是本地的[他讽刺地说]。日期是一种痛苦,(c)日期的出现我认为在
format()
之后不需要
toString()
(它已经返回了一个字符串)。
moment.utc('07-18-2013', 'MM-DD-YYYY').format('YYYY-MM-DD')