Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/455.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何计算JavaScript中两个时区的差异?_Javascript_Timezone_Momentjs - Fatal编程技术网

如何计算JavaScript中两个时区的差异?

如何计算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

例如,东部和中部的差异为1。我下面的解决方案让人感觉不舒服。有更简单/更好的方法吗

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
请记住,在美国,每个使用DST的时区实际上在不同的时刻切换。它们都在当地时间凌晨2:00切换,但不是在同一时间点

  • 芝加哥和纽约之间通常相隔1小时
  • 但每年有两个短暂的时段,它们要么相隔2小时,要么有相同的准确时间
另请参见中的“时区!=偏移”

关于时刻时区,你在评论中说:

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时区支持的环境中,这一点可以立即实现。这是目前大多数浏览器的特点

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');