在将Date转换为Epoch秒时从moment-timezone获取不正确的值

时间:2017-07-29 00:56:06

标签: javascript momentjs

我有一个用例,用户在其时区中选择日期和时间。在这种情况下,美国中部时间。我想将给定时区的日期转换为Epoch秒,我需要将其传递给第三方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
根据{{​​3}}

不正确

价值1501070400太早了5个小时。

如果我为日期传递一个天真的字符串:2017-07-26 12:00:00它按预期工作。

如果我使用天真的日期:new Date('2017-07-26 12:00:00');该值太早1小时,因为我的时区是美国东部。

我做错了什么?我认为时刻时区应该处理偏移量,占夏令时等等。

1 个答案:

答案 0 :(得分:2)

您的publishAt日期是使用以Z结尾的字符串创建的,因此它表示UTC时间。正如你可以看到publishAtgetTime())值,以毫秒为单位,因为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,因为您要告诉我们在芝加哥解析您的字符串,而new Date('2017-07-26 12:00:00')为您的本地时区创建日期。

请注意,时刻时区docs表示:

  

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>
&#13;
&#13;
&#13;

这是一个解析毫秒(15010704000001501088400000)的片段,然后以当地时间,UTC和芝加哥时区显示值。这类似于epochconverter.com所做的,也许可以帮助您理解网站显示这些结果的原因。

&#13;
&#13;
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
&#13;
<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>
&#13;
&#13;
&#13;

作为附加信息,请注意,时刻有unix()方法:

  

moment#unix输出一个Unix时间戳(自Unix Epoch以来的秒数)。

     

此值被覆盖到最接近的秒,并且不包括毫秒组件。

如果您希望避免1000除以valueOf()返回的值。

可能有用的其他阅读材料:Local vs UTC vs Offset指南,时区标记info page