如何获取时区别名的规范时区名称?

Posted

技术标签:

【中文标题】如何获取时区别名的规范时区名称?【英文标题】:How to get the canonical timezone name of a timezone alias? 【发布时间】:2021-11-28 01:47:25 【问题描述】:

我想创建一个函数,将时区别名转换为所述时区的规范名称。

Status of timezones from Wikipedia

例如,如果我有 Africa/Accra,我希望能够查找 Africa/Abidjan 是时区的规范名称。

function getCanonicalName(name) 
  // TODO

getCanonicalName('Africa/Accra'); // => 'Africa/Abidjan'

我自己调查过的事情

我曾尝试使用moment-timezoneluxon 来解析区域名称,但似乎没有办法将规范时区作为这些库的一部分进行逆向工程。

根据moment-timezone docs,您可以从“打包”数据表示中获取时区的规范名称,但在其源代码中looking at the implementation of pack,似乎只是通过source.name

luxon 有一个 normalizeZone 帮助器,但这似乎只是从各种输入类型返回一个 Zone 实例。但是,它不会规范化区域名称。 luxon Zones 上有一个isUniversal 标志,但是这个标志似乎与夏令时有关,而不是时区的状态。

【问题讨论】:

现在有guess() API吗? Link to Docs 谢谢,guess() API 足以获取当前用户的时区,但我们的服务还需要向管理员显示存储在用户记录中的用户时区信息。我们允许他们存储时区别名,但我们希望将它们标准化为规范时区,所以我认为 guess 是不够的。 【参考方案1】:

这可能无法将该特定区域识别为别名,因为它已在 September 2021 中更新:

但总的来说:

import moment from 'moment';
import momenttz from 'moment-timezone';

// From moment-timezone, but not exported
function normalizeName (name) 
  return (name || '').toLowerCase().replace(/\//g, '_');


function getCanonicalName(name) 
  const normalizedName = normalizeName(name);

  // A canonical zone might exist
  if (moment.tz._zones[normalizedName]) 
    return moment.tz._names[normalizedName];
  

  // If not, there'll be a link to a canonical name
  const canonicalZoneNormalized = moment.tz._links[normalizeName(name)];

  // And return the friendly name
  return moment.tz._names[canonicalZoneNormalized];


console.log(getCanonicalName('Pacific/Wallis')); // => Pacific/Tarawa
console.log(getCanonicalName('Pacific/Tarawa')); // => Pacific/Tarawa

【讨论】:

【参考方案2】:

鉴于时区数据库每年只更新一次,我认为我的解决方案是低维护。我在这里遵循一种非常粗略的方法。实际上,您可以先将 wikipedia 页面上显示的信息转换为 JSON,然后通过在浏览器控制台中运行它来获取包含所有时区及其规范时区的地图:

const keys = [];
const timezones = [];

$("table:first thead tr th").each(function () 
    keys.push($(this).text().replace(/\n/g, ''));
);

$("table:first tbody tr").each(function () 
    const obj = ;
    let i = 0;

    $(this).children("td").each(function () 
        obj[keys[i]] = $(this).text().replace(/\n/g, '');
        i++;
    );

    timezones.push(obj);
);

const canonicalTimezones = Object.assign(, ...timezones.map(x => ( [x['TZ database name']]: (x['Type'] === 'Canonical' ? x['TZ database name'] : x['Notes'].substring(8)) )));

JSON.stringify(canonicalTimezones);

您可以将输出保存在某个文件中。然后您只需要在代码中解析它并轻松获取相应的规范时区。

import canonicalTimezones from './canonicalTimezones.json';

function getCanonicalName(name) 
  return canonicalTimezones[name];

【讨论】:

以上是关于如何获取时区别名的规范时区名称?的主要内容,如果未能解决你的问题,请参考以下文章

如何获取完整的时区名称 ios

如何在 Postgres 9.3 中获取当前时区名称?

如何在 JavaScript 中获取时区名称?

如何在JavaScript中获取时区名称?

如何获取 pytz 时区的通用名称,例如。美国/纽约的 EST/EDT

.NET 通过时区名称获取时区偏移量