我有一个用例,用户在其时区中选择未来的日期和时间。在本例中为美国中部时间。我想将给定时区的日期转换为纪元秒,我需要将其传递给第三方 API。
到目前为止,这是我的部分单元测试代码:
moment.tz.add('America/Chicago');
// This value is returned by Mongoose as a Date, which is why I'm using Date() here
const publishAt = new Date('2017-07-26T12:00:00.000Z');
const publishAtEpoch = moment.tz(publishAt, 'America/Chicago').valueOf() / 1000;
这导致:
1501070400
而不是:
1501088400
根据以下情况,这是不正确的:https://www.epochconverter.com/timezones?q=1501070400&tz=America%2FChicago
值1501070400是提前 5 小时。
如果我为 Date: 传递一个朴素的字符串,2017-07-26 12:00:00
它会按预期工作。
如果我使用朴素的日期:new Date('2017-07-26 12:00:00');
该值早了 1 小时,因为我的时区是美国东部。
我做错了什么?我认为时刻时区应该处理偏移量,考虑夏令时等。
您的publishAt
日期是使用以Z
结尾的字符串创建的,因此它以 UTC 表示时间。正如你所看到的publishAt
(getTime()
(值以毫秒为单位,因为Unix纪元1501070400000
。
1501070400000
26 July 2017 12:00:00 UTC
(请参阅带有偏移量0
记录以秒为单位在链接中的表格中(。
在我看来,问题在于您期望获得1501088400000
而不是1501070400000
这是new Date('2017-07-26T12:00:00.000Z')
的"真正"价值。
moment.tz('2017-07-26 12:00:00', 'America/Chicago')
给出1501088400000
,因为您告诉 to moment 将字符串解析为芝加哥的时间,而new Date('2017-07-26 12:00:00')
为本地时区创建日期。
请注意,时刻时区文档指出:
Unix 时间戳和
Date
对象是指特定的时间点,因此在构造时使用时区偏移量是没有意义的。使用moment.tz(Number|Date, zone)
在功能上等效于moment(Number|Date).tz(zone)
。
这里有一个显示所描述结果的片段:
const publishAt = new Date('2017-07-26T12:00:00.000Z');
console.log(publishAt.getTime()); // 1501070400000
const publishAtEpoch = moment.tz(publishAt, 'America/Chicago').valueOf() / 1000;
console.log(publishAtEpoch); // 1501070400
const timeChicago = moment.tz('2017-07-26T12:00:00.000', 'America/Chicago');
console.log(timeChicago.valueOf() / 1000); // 1501088400
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js"></script>
这里有一个解析毫秒(1501070400000
和1501088400000
(的代码片段,然后它显示本地时间、UTC 和芝加哥时区的值。这与 epochconverter.com 所做的类似,也许可以帮助您了解网站显示这些结果的原因。
const m1Local = moment(1501070400000);
console.log(m1Local.format()); // 1501070400000 local time
const m1Utc = moment(1501070400000).utc();
console.log(m1Utc.format()); // 2017-07-26T12:00:00Z
const m1Chicago = moment(1501070400000).tz('America/Chicago');
console.log(m1Chicago.format()); // 2017-07-26T07:00:00-05:00
const m2Local = moment(1501088400000);
console.log(m2Local.format()); // 1501088400000 local time
const m2Utc = moment(1501088400000).utc();
console.log(m2Utc.format()); // 2017-07-26T17:00:00Z
const m2Chicago = moment(1501088400000).tz('America/Chicago');
console.log(m2Chicago.format()); // 2017-07-26T12:00:00-05:00
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.min.js"></script>
作为附加信息,请注意 moment 具有unix()
方法:
moment#unix
输出一个 Unix 时间戳(自 Unix 纪元以来的秒数(。此值下限到最接近的秒,并且不包括毫秒分量。
如果要避免除以1000
valueOf()
返回的值。
可能有用的更多阅读材料:本地与 UTC 与偏移指南,时区标签信息页面。