【问题标题】:Timezone offset solution working with different timezones使用不同时区的时区偏移解决方案
【发布时间】:2022-01-30 05:53:56
【问题描述】:

在处理多个时区时,我有一个案例,我在多个时区创建班次,现在用户申请这些班次。

它对时间非常敏感。现在我想输入班次所在的时区(例如Australia/Sydney) 解决方案:现在,在将其保存到数据库之前,我将时区转换为 UTCoffset,在示例 Australia/Sydney 时区中我设置偏移量,- 示例澳大利亚偏移量为 600,然后 -600 设置报价并存储到数据库中。

const getUTCOffset = timezone => Intl.DateTimeFormat([], {timeZone: timezone, timeZoneName: 'shortOffset'}).formatToParts().find(o => o.type === 'timeZoneName').value.match(/\-?\d+/)[0]*60;

(getUTCOffset('Australia/Sydney'))

这里有什么我遗漏的吗?什么是最佳解决方案?

【问题讨论】:

  • 当前代码会发生什么?期望什么?

标签: javascript node.js datetime timezone momentjs


【解决方案1】:

我认为您缺少的是由于历史变化和夏令时,偏移量会不时发生变化。您最好存储 IANA 位置并根据需要计算偏移量。

如果您想在几分钟内获得某个位置的偏移量(这很方便),请考虑:

function getOffsetInMinutes(loc, date = new Date()) {
  let [year, sign, hr, min] = date.toLocaleString('en', {
    year:'numeric',
    timeZone:loc,
    timeZoneName:'longOffset'
  }).match(/\d+|\+|\-/g);
  return (sign == '+'? 1 : -1) * (hr*60 + min*1);
}

['Asia/Kolkata',
 'Australia/Sydney',
 'America/New_York'
].forEach(
  loc => console.log(loc + ': ' + getOffsetInMinutes(loc))
);

对于不支持较新的 timeZoneName 选项值的浏览器(如 Safari),您可以使用使用“short”值的函数。以下返回偏移量为±HH:mm,不难修改为如上返回分钟。

// Return offset on date for loc in ±HH:mm format
function getTimezoneOffset(loc, date=new Date()) {
  // Try English to get offset. If get abbreviation, use French
  let offset;
  ['en','fr'].some(lang => {
    // Get parts - can't get just timeZoneName, must get one other part at least
    let parts = new Intl.DateTimeFormat(lang, {
      minute: 'numeric',
      timeZone: loc,
      timeZoneName:'short'
    }).formatToParts(date);
    // Get offset from parts
    let tzName = parts.filter(part => part.type == 'timeZoneName' && part.value);
    // timeZoneName starting with GMT or UTC is offset - keep and stop looping
    // Otherwise it's an abbreviation, keep looping
    if (/^(GMT|UTC)/.test(tzName[0].value)) {
      offset = tzName[0].value.replace(/GMT|UTC/,'') || '+0';
      return true;
    }
  });
  // Format offset as ±HH:mm
  // Normalise minus sign as ASCII minus (charCode 45)
  let sign = offset[0] == '\x2b'? '\x2b' : '\x2d';
  let [h, m] = offset.substring(1).split(':');
  return sign + h.padStart(2, '0') + ':' + (m || '00');
}

['Asia/Kolkata','Australia/Sydney','America/New_York'].forEach(
  loc => console.log(loc + ': ' + getTimezoneOffset(loc))
);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-17
    • 2020-07-11
    • 2013-06-24
    • 1970-01-01
    • 1970-01-01
    • 2013-07-11
    • 1970-01-01
    相关资源
    最近更新 更多