无法使用 moment.js 返回 UTC 日期时间
Posted
技术标签:
【中文标题】无法使用 moment.js 返回 UTC 日期时间【英文标题】:cannot return a utc datetime with moment.js 【发布时间】:2015-12-14 15:45:47 【问题描述】:试图将已经被 momentjs 转换为 UTC 的 datetime 对象传递给我的 MVC 控制器。我正在使用剑道 datetimepicker,出于某种原因,moment.utc 不会向控制器发送我想要的值。例如,我在我的剑道 datetimepicker 中输入“9/17/2015 12:00 AM”。我得到这个值:
var start = $("#startTime").val();
这给了我 "9/17/2015 12:00 AM" 。伟大的。然后我将其转换为日期对象:
var t1 = new Date(start);
读取为 Thu Sep 17 2015 00:00:00 GMT-0700 (Pacific Daylight Time) 。看起来还是不错的。接下来我尝试使用时刻转换为 UTC:
var t2 = moment.utc(t1);
这给了我
dt _isAMomentObject: true, _i: Thu Sep 17 2015 00:00:00 GMT-0700 (Pacific Daylight Time), _isUTC: true, _locale: fu, _d: Thu Sep 17 2015 00:00:0...
未转换为 UTC。而不是转换它似乎所做的一切是获取一个日期对象,让我告诉它“嘿,这是 UTC”,它说“好的”(通过标记 _isUTC:true),即使它仍然在那里保存 GMT 值
即使我决定先制作一个时刻对象,然后在其上运行 UTC?结果还是一样:
var t2 = moment(t1);
var t3 = moment.utc(t2);
因此,如果我在其中任何一个值上运行 .format()(这是我需要传递给我的控制器的内容),我总是会得到“2015-09-17T07:00:00+00:00”,这不是 UTC 时间。这是我输入的确切时间。我在这里做错了什么?
【问题讨论】:
【参考方案1】:一些事情:
甚至不要查看带有下划线前缀的字段。它们是 moment.js 内部设计的一部分,并不意味着直接使用。在许多情况下,必须组合几个字段才能获得正确的结果。这在公共 API 的函数中进行了说明,例如 format
。
不要依赖Date
对象来进行解析。跨浏览器的结果可能不一致。 Moment 有自己的解析器,您可以像这样使用它:
moment("9/17/2015 12:00 AM","M/D/YYYY h:mm A")
但是,在您的特定情况下,您实际上根本不需要解析任何字符串。你说你使用的是 Kendo 的 DateTimePicker
控件,所以你应该使用 value
函数,它已经返回了一个 Date
对象。
Moment 有两种不同的函数用于处理 UTC。
moment.utc(value)
- 根据 UTC 解释值
m.utc()
- 其中m
是任意时刻实例,将值转换为 UTC
请注意,第二个它通过将现有实例从“本地模式”切换到“UTC 模式”来改变现有实例。如果你想链接函数,它也会返回实例,但它也会修改原始实例。
如果您希望输出显示+00:00
偏移量,可以在转换为UTC 后使用format
。但是,如果您想显示 Z
(通常是首选),您可以直接调用 .toISOString()
而无需先明确转到 UTC - 因为该函数总是输出 UTC。
此外,大多数现代浏览器已经直接在Date
对象上支持.toISOString()
,因此除非您针对的是旧版浏览器,否则您可能根本不需要时间。
您说"2015-09-17T07:00:00+00:00"
不是UTC 时间,但实际上它是。您从 UTC-7 的 00:00 开始,相当于 UTC+0 的 7:00。因此,尽管跳过了几个不必要的步骤,但最终时刻仍然正确 - 至少在 t3
中是这样。
您可以使用以下任何一种来简化您的代码:
var picker = $("#startTime").data().kendoDateTimePicker;
var dt = picker.value(); // dt is a Date object
var m = moment(dt); // m is a moment object
m.utc(); // m has been converted to UTC
var s = m.format(); // ex: "2015-09-17T07:00:00+00:00"
或者……
var picker = $("#startTime").data().kendoDateTimePicker;
var dt = picker.value(); // dt is a Date object
var m = moment(dt); // m is a moment object
var s = m.toISOString(); // ex: "2015-09-17T07:00:00Z"
或者……
var picker = $("#startTime").data().kendoDateTimePicker;
var dt = picker.value(); // dt is a Date object
var s = dt.toISOString(); // ex: "2015-09-17T07:00:00Z" (requires browser support)
【讨论】:
谢谢,这很有帮助。奇怪的是它仍然不适合我,我确保 javascript 工作正常(plnkr.co/edit/JchbfJqAwJwIr8zm803K?p=preview),但显然我遇到的其他问题之一是我的 MVC 控制器将 datetime 参数作为输入。由于某种原因,这将对象 BACK 转换为本地时间。一旦我将该参数更改为字符串,它就可以正常工作。诡异的。谢谢! 是的,这可能是 ASP.NET MVC 的问题。尽管如果您改用 WebAPI,则不会有这个问题,因为反序列化是由 JSON.net 处理的。你也可以试试DateTimeOffset
。以上是关于无法使用 moment.js 返回 UTC 日期时间的主要内容,如果未能解决你的问题,请参考以下文章