如何计算JavaScript中两个时区的差异?
例如,东部和中部的差异为1。我下面的解决方案让人感觉不舒服。有更简单/更好的方法吗如何计算JavaScript中两个时区的差异?,javascript,timezone,momentjs,Javascript,Timezone,Momentjs,例如,东部和中部的差异为1。我下面的解决方案让人感觉不舒服。有更简单/更好的方法吗 var diff = (parseInt(moment().tz("America/New_York").format("ZZ")) - parseInt(moment().tz("America/Chicago").format("ZZ"))) / 100; 我的示例是使用库。不可能计算两个任意时区之间的差异。您只能计算特定时刻的差异 伦敦和纽约目前相差4小时(2015年3月25日撰写此文) 但几周前相差5
var diff = (parseInt(moment().tz("America/New_York").format("ZZ")) - parseInt(moment().tz("America/Chicago").format("ZZ"))) / 100;
我的示例是使用库。不可能计算两个任意时区之间的差异。您只能计算特定时刻的差异
- 伦敦和纽约目前相差4小时(2015年3月25日撰写此文)
- 但几周前相差5个小时,几周后也将相差5个小时
- 每个时区在不同的时间点切换夏令时的偏移
- 伦敦和巴黎之间总是有一个小时,因为他们在同一时间转换
- 亚利桑那州和夏威夷之间总是有3个小时,因为两者都没有DST
- 芝加哥和纽约之间通常相隔1小时
- 但每年有两个短暂的时段,它们要么相隔2小时,要么有相同的准确时间
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时区支持的环境中,这一点可以立即实现。这是目前大多数浏览器的特点
function getTimeZoneOffset(date, timeZone) {
// Abuse the Intl API to get a local ISO 8601 string for a given time zone.
let iso = date.toLocaleString('en-CA', { timeZone, hour12: false }).replace(', ', 'T');
// Include the milliseconds from the original timestamp
iso += '.' + date.getMilliseconds().toString().padStart(3, '0');
// Lie to the Date object constructor that it's a UTC time.
const lie = new Date(iso + 'Z');
// Return the difference in timestamps, as minutes
// Positive values are West of GMT, opposite of ISO 8601
// this matches the output of `Date.getTimeZoneOffset`
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中工作,其中安装了完整icu
支持(这是Node 13及更新版本的默认设置)。如果您的旧版本带有系统icu
或小型icu
,则可以使用此修改后的功能。它也可以在浏览器和完整的icu
环境中工作,但要大一点。(我已经在Linux上的节点8.17.0和Windows上的节点12.13.1上对此进行了测试。)
请注意,无论采用哪种方式,我们都必须通过
Intl
才能正确应用时区。由于夏令时()等原因,两个时区之间的差异只能通过特定时间来测量
但是,对于特定的日期,下面的代码应该可以工作
function getOffsetBetweenTimezonesForDate(date, timezone1, timezone2) {
const timezone1Date = convertDateToAnotherTimeZone(date, timezone1);
const timezone2Date = convertDateToAnotherTimeZone(date, timezone2);
return timezone1Date.getTime() - timezone2Date.getTime();
}
function convertDateToAnotherTimeZone(date, timezone) {
const dateString = date.toLocaleString('en-US', {
timeZone: timezone
});
return new Date(dateString);
}
偏移量/差值以毫秒为单位
那么你所要做的就是:
const offset = getOffsetBetweenTimezonesForDate(date, 'America/New_York', 'America/Chicago');
减去?那么类似于
(moment().tz(“America/New_York”).zone()-moment().zone())/60
?我想这样会好一点。你打算用它做什么?您真的需要按名称使用时区吗?在本例中,我们需要。web服务器位于东部时区;我们在中环。我需要用户时区和服务器之间的差异。使用node.js尝试了一下,但它不起作用-当解析此日期字符串时,这行不起作用const lie=new Date(iso+'Z')
结果是NaN
。但也许我的节点太旧了v8.3.0
@AlexeyPetrushin-谢谢你指出这一点。问题是Node.js v13之前的版本默认带有small-icu
,它不支持区域设置-因此您可以使用系统区域设置格式(不支持en-CA
y-m-d格式)。我已经扩展了我的答案,使用formatParts
API包含了另一种方法。这在不更新节点的情况下应该对您有效。@erkkkhopra-IE11支持toLocaleString
,但不支持IANA时区。如果您既需要时区支持,也需要对IE11和其他旧浏览器的支持,那么您需要使用一个自带时区数据的旧库,而不是依赖Intl
。例如,干得好!注意:const hour=map.get('hour')
有时返回“24”,这导致iso字符串无效。它需要一个hour==“24”?“00”:小时代码>选中放置在某个位置以修复它。这是节点v12+BTW的情况。另外,对结果进行舍入也没有什么坏处。我遇到了一些恼人的单元测试失败,因为-0!==0
。很有趣。虽然,24意味着第二天的0,所以在哪里会有更多的数学要做。也许最容易调整谎言。或者,我想知道是否有一个Intl设置来避免这样的结果。也许传递某些特定的区域设置比传递未定义的更好。(顺便说一句,我会正确地解决这个问题。)请看-你的答案没有提供任何新的信息。
const offset = getOffsetBetweenTimezonesForDate(date, 'America/New_York', 'America/Chicago');