使用Javascript从时区名称获取时区偏移量

29

我发现了很多解决方案可以从偏移值获取时区名称。但是我有时区名称,我想要该时区的偏移值。我尝试了setTimezone('Asia/Kolkata'),但我认为没有像setTimezone这样的方法。

例子:

Asia/Kolkata should give me -330 ( offset )

你尝试过 http://momentjs.com/ 吗? - Anto Subash
让我看看我是否理解了您的情况。您有一个时区A,想要获取与其他时区B之间的时间差。我的问题是,您的变量是这两个时区吗?因此,这两个时区都会经常更改吗?还是只有其中一个时区可能会更改,例如,有一个客户端具有一个时区,您只想知道客户端与服务器之间的时间差? - user688877
只有一个时区会改变...服务器的时区是固定的,它是UTC 0。当客户端时区为Asia/Kolkata时,我希望得到该时区的偏移量(即-330分钟)。 - Hardik Sondagar
4个回答

27
这绝对是使用现代JavaScript完成此任务的最简单方法。 注意:请记住,偏移量取决于夏令时(DST)是否激活。
/* @return A timezone offset in minutes */
const getOffset = (timeZone = 'UTC', date = new Date()) => {
  const utcDate = new Date(date.toLocaleString('en-US', { timeZone: 'UTC' }));
  const tzDate = new Date(date.toLocaleString('en-US', { timeZone }));
  return (tzDate.getTime() - utcDate.getTime()) / 6e4;
}

console.log(`No arguments: ${getOffset()}`); // 0

{
  console.log('! Test Case #1 >> Now');
  console.log(`Asia/Colombo     : ${getOffset('Asia/Colombo')}`);     //  330
  console.log(`America/New_York : ${getOffset('America/New_York')}`); // -240
}

{
  console.log('! Test Case #2 >> DST : off');
  const date = new Date(2021, 0, 1);
  console.log(`Asia/Colombo     : ${getOffset('Asia/Colombo', date)}`);     //  330
  console.log(`America/New_York : ${getOffset('America/New_York', date)}`); // -300
}

{
  console.log('! Test Case #3 >> DST : on');
  const date = new Date(2021, 5, 1);
  console.log(`Asia/Colombo     : ${getOffset('Asia/Colombo', date)}`);     //  330
  console.log(`America/New_York : ${getOffset('America/New_York', date)}`); // -240
}
.as-console-wrapper { top: 0; max-height: 100% !important; }


我有两个建议:1. 使用Date.parse()代替new Date()。2. 将字符串' Z'添加到toLocaleString()的输出中,并且该函数根据夏令时是否激活而给出不同的偏移量:Date.parse(date.toLocaleString(systemTimeZone, { timeZone }) + ' Z') - some

12

我遇到了同样的问题,这是我想出的解决方案,如果你能获取一个像你提到的IANA tz 数据库名称

const myTimezoneName = "Asia/Colombo";
 
// Generating the formatted text
// Setting the timeZoneName to longOffset will convert PDT to GMT-07:00
const options = {timeZone: myTimezoneName, timeZoneName: "longOffset"};
const dateText = Intl.DateTimeFormat([], options).format(new Date);
 
// Scraping the numbers we want from the text
// The default value '+0' is needed when the timezone is missing the number part. Ex. Africa/Bamako --> GMT
let timezoneString = dateText.split(" ")[1].slice(3) || '+0';

// Getting the offset
let timezoneOffset = parseInt(timezoneString.split(':')[0])*60;

// Checking for a minutes offset and adding if appropriate
if (timezoneString.includes(":")) {
   timezoneOffset = timezoneOffset + parseInt(timezoneString.split(':')[1]);
}

这不是一个非常好的解决方案,但它可以在不导入任何内容的情况下完成工作。它依赖于 Intl.DateTimeFormat 的输出格式始终保持一致,这应该是如此,但这是一个潜在的警告。


1
谢谢!经过长时间的搜索,我终于在这里找到了答案。非常感激。 - Armando
请注意,它不总是有效的,因为在“短”格式中,有些时区用它们的名称表示,例如“PST”,而不是它们的偏移量。更好的方法是以“shortOffset”格式打印时区,但是Node.js不支持此选项。 - Alexander Korostin
Node.js现在支持针对timeZoneName的"shortOffset"和"longOffset"选项。 - diachedelic
1
好的回答。但是它需要微调。从文本中提取数字的那一行对于解析为GMT而不是GMT+0的时区无效。我将更新答案以添加修复程序。 - asiby
@AlexanderKorostin,使用“longOffset”作为时区格式将解决这个问题。我已经再次编辑了答案来解决这个问题。 - asiby

5
你仅凭名称无法获得它。你还需要知道具体的时间。尽管Asia/Kolkata可能固定为单个偏移量,但许多时区在标准时间和夏令时之间交替,因此你只能获取一个偏移量,而不能获取唯一的偏移量。
若要了解如何在JavaScript中实现,请参见此答案

3
使用国家和时区 npm包:
import {getTimezone} from 'countries-and-timezones';
const australianTimezone = 'Australia/Melbourne';
console.log(getTimezone(australianTimezone));

打印到控制台:

{
  name: 'Australia/Melbourne',
  country: 'AU',
  utcOffset: 600,
  utcOffsetStr: '+10:00',
  dstOffset: 660,
  dstOffsetStr: '+11:00',
  aliasOf: null
}

从那里开始,您可以根据是否为夏令时使用utcOffset或dstOffset。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接