将日期转换为纪元秒时从时刻时区获取不正确的值



我有一个用例,用户在其时区中选择未来的日期和时间。在本例中为美国中部时间。我想将给定时区的日期转换为纪元秒,我需要将其传递给第三方 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

150107040000026 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>

这里有一个解析毫秒(15010704000001501088400000(的代码片段,然后它显示本地时间、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 纪元以来的秒数(。

此值下限到最接近的秒,并且不包括毫秒分量。

如果要避免除以1000valueOf()返回的值。

可能有用的更多阅读材料:本地与 UTC 与偏移指南,时区标签信息页面。

最新更新