Удобные имена часовых поясов, соответствующие именам IANA - PullRequest
1 голос
/ 13 апреля 2020

Я пытаюсь найти удобный для пользователя список часовых поясов, чтобы пользователи могли выбрать свой текущий часовой пояс. Он будет иметь общие названия часовых поясов, таких как Pacifi c Время (США и Канада) .

Этот список должен сопоставить текст со стандартным именем IANA, таким как America / Los_Angeles .

Также удаляются списки, которые пользователь считает "тем же" часовым поясом. Например, список для Pacifi c Time (США и Канада) будет соответствовать America / Los_Angeles и America / Tijuana, которые являются "тем же" временем.

Я пытался найти в Базе данных часовых поясов IANA , Интерфейс API ECMA Script и такие библиотеки, как Момент. js. Они могут анализировать имя IANA в общее имя, например America/Los_Angeles ==> "Pacific Standard Time", но не имеют встроенной функции для перечисления всех общих имен и соответствующих им имен IANA.

1 Ответ

1 голос
/ 14 апреля 2020

Короткий ответ: не существует простой карты от репрезентативных имен местоположений IANA к общим именам, потому что имя IANA не отражает исторические изменения c в смещении или переходе на летнее время, и общие имена недостаточно стандартизированы ни официально, ни de facto .

Длинный ответ

Репрезентативные местоположения IANA включают в себя исторические изменения c смещения часового пояса, как для местного времени, так и для перехода на летнее время, как это было применено за эти годы , Стандартное название часового пояса, вероятно, не изменилось, однако смещения изменились и продолжаются. Кроме того, репрезентативное имя местоположения IANA остается неизменным при переходе на летнее время, однако смещение и общее имя не имеют.

Например, Самоа имеет название IANA "Pacific / Samoa". Его стандартное смещение до 29 декабря 2011 года было UTC-11: 00, но после этого его смещение было UTC + 13: 00, а летнее время переходило с UT C -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 вышеприведенное значение дает для Самоа смещение UT C -1100, поэтому все еще используются старые значения, и он не распознает летнее время, поэтому на объект Intl нельзя положиться.

Вы можете использовать объект Intl, как показано ниже, отметив, что для некоторых местоположений у него может не быть имени для часового пояса, поэтому просто показывает смещение (например, попробуйте Европа / Астрахань). В IANA насчитывается около 600 мест.

// 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>
...