在Javascript中从时区获取utc偏移量

use*_*032 10 javascript timezone datejs

我需要一个给出时区的Javascript函数,返回当前的utc偏移量.

例如,theFuncIneed('US/Eastern') - > 240

任何的想法?

谢谢

Jia*_*ang 14

现在使用Intl API已经成为可能:

的实现Intl是基于icu4c的。如果您挖掘源代码,您会发现时区名称因区域设置而异,例如:

for (const locale of ["ja", "en", "fr"]) {
  const timeZoneName = Intl.DateTimeFormat(locale, {
    timeZoneName: "short",
    timeZone: "Asia/Tokyo",
  })
    .formatToParts()
    .find((i) => i.type === "timeZoneName").value;
  console.log(timeZoneName);
}
Run Code Online (Sandbox Code Playgroud)

幸运的是,有一个语言环境Interlingua(语言标签是ia),它对时区名称使用相同的模式(例如GMT+11:00)。

下面的代码片段可以满足您的需求:

const getOffset = (timeZone) => {
  const timeZoneName = Intl.DateTimeFormat("ia", {
    timeZoneName: "short",
    timeZone,
  })
    .formatToParts()
    .find((i) => i.type === "timeZoneName").value;
  const offset = timeZoneName.slice(3);
  if (!offset) return 0;

  const matchData = offset.match(/([+-])(\d+)(?::(\d+))?/);
  if (!matchData) throw `cannot parse timezone name: ${timeZoneName}`;

  const [, sign, hour, minute] = matchData;
  let result = parseInt(hour) * 60;
  if (sign === "+") result *= -1;
  if (minute) result += parseInt(minute);

  return result;
};

console.log(getOffset("US/Eastern")); // 240
console.log(getOffset("Atlantic/Reykjavik")); // 0
console.log(getOffset("Asia/Tokyo")); // -540
Run Code Online (Sandbox Code Playgroud)

这种方法可能有点棘手,但在我的生产项目中效果很好。我希望它也对你有帮助:)

更新

非常感谢 Bort 指出错误。我已经更正了该片段。

  • 将 `timeZoneName: "short",` 更改为 `timeZoneName: "shortOffset",` 似乎可以修复此代码片段,使其可以在 Chrome 100、Firefox 99 和 Node 18 中运行。我尚未测试其他浏览器或节点版本。否则,指定时区“US/Eastern”将返回 timeZoneName“EDT”,其中不包含可解析的 GMT 偏移量。 (3认同)
  • @kleinfreund奇怪的是,当我运行第二个代码片段时,我得到 `console.log(getOffset("US/Eastern"));` 的 `0` (2认同)
  • 符号/分钟行有错误。应该先是 `if (min) result += parseInt(mint);` 然后是 `if (sign === "+") result *= -1;` 否则所有包含分钟的时区偏移量都会被错误计算。例如,亚洲/加尔各答偏移量为 5.5,这意味着它应该为 -330,但您的代码给出 -270。 (2认同)

Mat*_*int 8

一般来说,这是不可能的。

  • US/Eastern时区的标识符。(它实际上是 的别名America/New_York,它是真正的标识符。)

  • 240是时区偏移量。更常见的写法是-04:00 (反转符号,除以 60)。

  • 美国东部时区由东部标准时间(偏移量为 )-05:00和东部夏令时(偏移量为 )组成-04:00

所以说US/Eastern= 240一点也不准确。请阅读时区标签维基,尤其是标题为“时区!= 偏移”的部分。

现在您确实要求了当前偏移量,这可能的。如果您提供日期+时间参考,则可以解决此问题。

  • 对于执行 javascript 代码的计算机的本地时区,这是.getTimeZoneOffset()Date对象的任何实例内置的。

  • 但是,如果您希望在特定时区使用它,则需要使用我在此处列出的库之一

  • `.getTimeZoneOffset()` 应该是不带大写 Z 的 `.getTimezoneOffset()` (6认同)

ran*_*bey 6

以下函数可用于返回给定时区的 UTC 偏移量:

const getTimezoneOffset = (timeZone, date = new Date()) => {
  const tz = date.toLocaleString("en", {timeZone, timeStyle: "long"}).split(" ").slice(-1)[0];
  const dateString = date.toString();
  const offset = Date.parse(`${dateString} UTC`) - Date.parse(`${dateString} ${tz}`);
  
  // return UTC offset in millis
  return offset;
}
Run Code Online (Sandbox Code Playgroud)

它可以像这样使用:

const offset = getTimezoneOffset("Europe/London");
console.log(offset);
// expected output => 3600000
Run Code Online (Sandbox Code Playgroud)

  • 这有点不正确。对于落后的时区,UTC 偏移量应为正值,对于领先的时区,UTC 偏移量应为负值。因此,需要反转减法:`Date.parse(\`${dateString} ${tz}\`) - Date.parse(\`${dateString} UTC\`);`。否则,它不会与内置的“Date.prototype.getTimezoneOffset”保持一致。 (4认同)
  • 另外,“Europe/London”的预期输出应该是“0” (2认同)
  • @Avraham 偏移量取决于夏令时的日期。这就是为什么该函数将日期作为第二个参数 (2认同)