如何使用 moment.js 获取 2 个不同时区中同一日期的 unix 时间戳?

How to obtain unix timestamps for same date in 2 different time zones with moment.js?

我正在开发一个应用程序,用户可以在其中选择他们记录时间所在的时区。但在内部,我想将时间存储为 unix 时间戳。

假设我有一个约会“2016-01-01 1:00 下午”。如果我将此日期存储在 CDT (America/Chicago) 中,我的理解是生成的 unix 时间戳应该与我在 MDT (America/Denver) 中存储的相同日期不同。但是,我得到了两个日期相同的 unix 时间戳,我无法理解为什么。

var chicagoDate = moment('2016-01-01 1:00 pm').tz('America/Chicago');
var denverDate = moment('2016-01-01 1:00 pm').tz('America/Denver');

chicagoDate.format();
// "2016-01-01T07:00:00-06:00"
denverDate.format();
// "2016-01-01T06:00:00-07:00"

到目前为止,这证实了这 2 个日期彼此不同,如使用 format() 获得的 UTC 表示所示。但这是我感到困惑的地方:

chicagoDate.unix();
// 1451653200
denverDate.unix();
// 1451653200

2 个不同的 UTC 日期不应该产生 2 个不同的 unix 时间戳吗?

在:

moment('2016-01-01 1:00 pm').tz('America/Chicago');

没有解析格式参数,所以 moment.js 查看格式是否是它可以在没有格式的情况下解析的格式。它不能,所以它回退到内置的解析器,就好像你写的一样:

moment(new Date('2016-01-01 1:00 pm')).tz('America/Chicago');

并在控制台中发出警告:

Deprecation warning: value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions…

Safari 至少将其解析为无效日期(时间戳),因此您应该包括解析格式:

moment(new Date('2016-01-01 1:00 pm', 'YYYY-MM-DD h:mm a')).tz('America/Chicago');

其次,字符串被解析为本地字符串,因为没有与时间戳关联的时区。因此,这两行代码产生完全相同的时间值(即与纪元的偏移量)并且产生的两个日期实际上是相同的。

tz 的调用设置了用于所有后续操作的时区,因此输出显示不同的时间,因为在格式化阶段应用了不同的偏移量。实际格式化的日期实际上仍然相同。

如果您希望字符串被解析为另一个时区,您需要在解析阶段手动将其包含在字符串中(例如“-06:00”或其他),或者使用像 Luxon 带有 IANA 位置(例如 'America/Chicago')。