如何获取时区别名的规范时区名称?
How to get the canonical timezone name of a timezone alias?
我想创建一个函数,将时区别名转换为所述时区的规范名称。
Status of timezones from Wikipedia
例如,如果我有 Africa/Accra
,我希望能够查找 Africa/Abidjan
是时区的规范名称。
function getCanonicalName(name) {
// TODO
}
getCanonicalName('Africa/Accra'); // => 'Africa/Abidjan'
我自己调查过的事情
我曾尝试使用 moment-timezone
和 luxon
来解析时区名称,但似乎没有办法将规范时区作为这些库的一部分进行逆向工程。
根据他们的源代码中的moment-timezone
docs, you can get the Canonical Name of a timezone from the "packed" data representation, but looking at the implementation of pack
,似乎只是通过source.name
。
luxon
有一个 normalizeZone
帮助程序,但它似乎只是 return 一个来自各种输入类型的 Zone
实例。但是,它不会规范化区域名称。 luxon Zone
s 上有一个 isUniversal
标志,但是这个标志似乎与 DST 有关,而不是时区状态。
鉴于时区数据库每年仅更新一次,我认为我的解决方案维护成本低。我在这里遵循一种非常粗略的方法。实际上,您可以首先将维基百科页面上显示的信息获取到 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];
}
这可能无法将特定区域识别为别名,因为它已在 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
我想创建一个函数,将时区别名转换为所述时区的规范名称。
Status of timezones from Wikipedia
例如,如果我有 Africa/Accra
,我希望能够查找 Africa/Abidjan
是时区的规范名称。
function getCanonicalName(name) {
// TODO
}
getCanonicalName('Africa/Accra'); // => 'Africa/Abidjan'
我自己调查过的事情
我曾尝试使用 moment-timezone
和 luxon
来解析时区名称,但似乎没有办法将规范时区作为这些库的一部分进行逆向工程。
根据他们的源代码中的moment-timezone
docs, you can get the Canonical Name of a timezone from the "packed" data representation, but looking at the implementation of pack
,似乎只是通过source.name
。
luxon
有一个 normalizeZone
帮助程序,但它似乎只是 return 一个来自各种输入类型的 Zone
实例。但是,它不会规范化区域名称。 luxon Zone
s 上有一个 isUniversal
标志,但是这个标志似乎与 DST 有关,而不是时区状态。
鉴于时区数据库每年仅更新一次,我认为我的解决方案维护成本低。我在这里遵循一种非常粗略的方法。实际上,您可以首先将维基百科页面上显示的信息获取到 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];
}
这可能无法将特定区域识别为别名,因为它已在 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