我试图找到一个用户友好的时区列表,让用户选择他们的当前时区。它将有相同的名称,即所指的时区,如太平洋时间(美国和加拿大)。
此列表应将文本映射到IANA标准名称,如America/Los_Angeles.。
它还将删除用户认为是“相同”时区的列表。例如,Pacific time (美国和加拿大)的列表将对应于美国/洛杉矶和美国/蒂华纳,它们是“相同的”时间。
我试过查看IANA时区数据库、ECMA脚本国际化API和Moment.js这样的库。它们可以将IANA名称解析为公共名称,例如America/Los_Angeles ==> "Pacific Standard Time",但是没有一个内置函数来列出所有公共名称及其对应的IANA名称。
发布于 2020-04-13 23:19:41
简单的回答是,从IANA代表的位置名称到通用名称没有简单的地图,因为IANA名称没有反映偏移量或夏时制方面的历史变化,也没有正式或事实上充分标准化通用名称。
长答案
IANA具有代表性的地点包括时区偏移的历史性变化,包括当地时间和夏令,因为这些年来一直在使用。标准时区名称可能没有更改,但是偏移已经并将继续更改。另外,IANA代表的位置名称在夏令期间保持不变,但是偏移量和普通名称不一样。
例如,萨摩亚的IANA名称为“Pacific/萨摩亚”。它在2011年12月29日之前的标准偏移量是UTC−11:00,但之后它的偏移量是UTC+13:00,它的夏令时从UTC-1000转到了UTC+14:00。时区的常用名称是“萨摩亚标准时间”和“萨摩亚夏时制”,但这些名称没有标准化,而且在许多地方含糊不清(例如,CST可能是2或3个不同地点的中央标准时间,或中国标准时间)。
因此,从IANA代表的位置名称到所有IANA位置的公共时区名称没有简单的地图。您可能可以为一个小的子集创建一个,但是使用内置的Intl对象可能更简单。
let opts = {
hour: 'numeric',
minute:'2-digit',
timeZone: 'Pacific/Samoa',
timeZoneName: 'long'
};
let time = new Date().toLocaleString('en', opts);
console.log('Currently in Samoa it\'s ' + time);
备注
在最新版本的MacOS上,上面给出了一个用于萨摩亚UTC-1100的偏移量,因此仍然使用旧值,而且它不识别夏时制,因此不能依赖Intl对象。
您可以如下所示使用Intl对象,请注意,对于某些位置,它可能没有时区的名称,因此只显示偏移量(例如,try Europe/Astrakhan)。有近600个IANA地点。
// Detect user representative location if available
let repLoc = (typeof Intl == 'object' &&
typeof Intl.DateTimeFormat == 'function' &&
typeof Intl.DateTimeFormat().resolvedOptions == 'function')?
Intl.DateTimeFormat().resolvedOptions().timeZone : 'default';
function setRepLoc(evt) {
showSampleDates(this.value);
}
function showSampleDates(repLoc) {
let el0 = document.getElementById('sDate0');
let el1 = document.getElementById('sOff0');
let el2 = document.getElementById('sDate1');
let el3 = document.getElementById('sOff1');
let d0 = new Date(Date.UTC(2020,0,1,11));
let d1 = new Date(Date.UTC(2020,5,1,11));
let opts = {
weekday: 'short',
day: 'numeric',
month: 'short',
year: 'numeric',
hour: 'numeric',
minute: '2-digit',
timeZone: repLoc,
timeZoneName: 'long'
};
let offOpts = {
hour: 'numeric',
hour12: false,
timeZone: repLoc,
timeZoneName: 'short'
}
if (repLoc == 'default') {
el0.textContent = '';
el1.textContent = '';
el2.textContent = '';
el3.textContent = '';
} else {
el0.textContent = d0.toLocaleString('en-NZ', opts);
el1.textContent = d0.toLocaleString('en-NZ', offOpts).split(' ')[1];
el2.textContent = d1.toLocaleString('en-NZ', opts);
el3.textContent = d1.toLocaleString('en-NZ', offOpts).split(' ')[1];
}
}
window.onload = function(){
let sel = document.getElementById('repLoc')
if (repLoc) {
sel.options[0].text = repLoc;
sel.options[0].value = repLoc;
sel.selectedIndex = 0;
setRepLoc.call(sel);
}
sel.addEventListener(
'change',
setRepLoc,
false);
};td:nth-child(1){text-align:right;color:#999;}
td:nth-child(2){font-family:monospace}<table>
<tr>
<td>IANA loc:
<td><select id="repLoc">
<option selected value="default">Select a location
<option>Europe/Amsterdam
<option>Europe/Andorra
<option>Europe/Astrakhan
<option>Europe/Athens
<option>Europe/Belfast
<option>Pacific/Samoa
<option>Pacific/Kiritimati
<option>Antarctica/DumontDUrville
<option>Antarctica/Davis
<option>America/Chicago
<option>Australia/Brisbane
</select>
<tr>
<td>Sample:
<td id="sDate0">
<tr>
<td>Offset:
<td id="sOff0">
<tr>
<td>Sample:
<td id="sDate1">
<tr>
<td>Offset:
<td id="sOff1">
</table>
发布于 2021-09-07 08:16:29
您可以使用Intl.DateTimeFormat.prototype.formatToParts()。
new Intl.DateTimeFormat(
'default',
{ timeZone: 'America/Los_Angeles', timeZoneName: 'long' }
).formatToParts().find(({ type }) => type === 'timeZoneName').value
// 'Pacific Daylight Time'发布于 2022-02-11 23:11:41
在Kimamula回答的基础上,我获取了IANA时区名称的当前列表,并在浏览器的Intl格式化程序中运行它,以获得所有时区名称的长和短名称。结果是一个带有IANA名称到人类可读的名称的映射的要点。我采用了这些名字的“通用”形式,没有提到夏令时。否则,我们需要知道DST是否有效来选择名称。(例如太平洋时间而不是太平洋标准时间或太平洋夏时制)。
不是每个时区在这个数据库中都有一个理想的名称,因为大多数与时间相关的东西,这将是一个不完美的解决方案。但它有望涵盖最受用户欢迎的时区,显示IANA名称作为后盾是一种选择。
如果您想自己生成这些名称,您可以在浏览器中运行这些名称。这些名称来自Firefox,我猜想它们与实现有关,在其他浏览器中可能有些不同。
const iana_names = [
"Africa/Abidjan",
"Africa/Accra",
"Africa/Addis_Ababa",
// ...
"W-SU",
"WET",
"Zulu"
]
const mapping = {}
iana_names.forEach( name => {
const long = new Intl.DateTimeFormat('default', { timeZone: name, timeZoneName: 'longGeneric' }).formatToParts().find(({ type }) => type === 'timeZoneName').value
const short = new Intl.DateTimeFormat('default', { timeZone: name, timeZoneName: 'shortGeneric' }).formatToParts().find(({ type }) => type === 'timeZoneName').value
mapping[name] = {
long, short
}
})https://stackoverflow.com/questions/61186388
复制相似问题