无法计算任意两个时区之间的差异。您只能为特定时间计算差异。
- 目前伦敦和纽约之间相差4个小时(此内容编写于2015年3月25日)。
- 几周前它们之间相差5个小时,几周后也将是5个小时。
- 每个时区在不同时刻转换夏令时偏移量。
这在两个时区之间的一般情况下是正确的。但是,有些时区要么完全同时切换,要么根本不切换。
- 伦敦和巴黎之间始终相差1小时,因为它们同时切换。
- 亚利桑那州和夏威夷之间始终相差3个小时,因为两者都没有夏令时。
请记住,在美国,每个使用夏令时的时区实际上在不同的时间切换。它们都在当地时间早上2点切换,但不是在同一个世界标准时间切换。
- 在芝加哥和纽约之间通常相差1小时。
- 但是每年有两个短暂的时期,它们要么相差2小时,要么时间完全相同。
请参见时区标签百科中的“时区!=偏移量”。
现在关于moment-timezone,您在评论中说:
Web服务器位于东部时区;我们在中部。我需要用户时区与服务器之间的差异。
Web服务器的时区无关紧要。您应该能够在世界上任何地方托管而不影响您的应用程序。如果不能,则做错了。
您可以获取当前时间差,以及用户所在时区(美国中部时间)与您的时区之间的差异。如果代码在浏览器中运行,则甚至不需要知道用户的确切时区:
var now = moment();
var localOffset = now.utcOffset();
now.tz("America/Chicago"); // your time zone, not necessarily the server's
var centralOffset = now.utcOffset();
var diffInMinutes = localOffset - centralOffset;
如果代码是在服务器上运行(在node.js应用程序中),那么你需要知道用户的时区。只需像这样更改第一行即可:
var now = moment.tz("America/New_York"); // their time zone
更新的答案:
在支持ECMAScript国际化API并完全实现IANA时区支持的环境中,可以在不使用Moment的情况下完成。这在大多数现代浏览器中都是可行的。
function getTimeZoneOffset(date, timeZone) {
let iso = date.toLocaleString('en-CA', { timeZone, hour12: false }).replace(', ', 'T');
iso += '.' + date.getMilliseconds().toString().padStart(3, '0');
const lie = new Date(iso + 'Z');
return -(lie - date) / 60 / 1000;
}
使用示例:
getTimeZoneOffset(new Date(2020, 3, 13), 'America/New_York') //=> 240
getTimeZoneOffset(new Date(2020, 3, 13), 'Asia/Shanghai') //=> -480
如果您想知道它们之间的差异,只需简单地减去结果即可。
Node.js
上述函数适用于安装了
国际化支持的Node.js(对于Node 13及更高版本,这是默认设置)。如果您使用旧版本的
system-icu
或
small-icu
,则可以使用此修改后的函数。它也适用于浏览器和
full-icu
环境,但稍微大一些。(我已在Linux上的Node 8.17.0和Windows上的Node 12.13.1上测试过此功能。)
function getTimeZoneOffset(date, timeZone) {
const options = {timeZone, calendar: 'iso8601', year: 'numeric', month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit', second: '2-digit', hour12: false};
const dateTimeFormat = new Intl.DateTimeFormat(undefined, options);
const parts = dateTimeFormat.formatToParts(date);
const map = new Map(parts.map(x => [x.type, x.value]));
const year = map.get('year');
const month = map.get('month');
const day = map.get('day');
const hour = `${map.get('hour') % 24}`.padStart(2, "0");
const minute = map.get('minute');
const second = map.get('second');
const ms = date.getMilliseconds().toString().padStart(3, '0');
const iso = `${year}-${month}-${day}T${hour}:${minute}:${second}.${ms}`;
const lie = new Date(iso + 'Z');
return -(lie - date) / 60 / 1000;
}
请注意,无论哪种方式,我们都
必须通过
Intl
来正确应用时区。
(moment().tz("America/New_York").zone() - moment().zone()) / 60
这样?我想这样好些。 - Homer