Comment obtenir la liste des identifiants de fuseaux horaires valides

Récupérer tous les identifiants de fuseaux horaires IANA pris en charge en JavaScript pour créer des menus déroulants et valider les entrées utilisateur

Introduction

Lors de la création de fonctionnalités permettant aux utilisateurs de sélectionner leur fuseau horaire, vous devez connaître les identifiants de fuseau horaire valides. Un utilisateur à New York pourrait avoir besoin de choisir America/New_York, tandis qu'un utilisateur à Tokyo aurait besoin de Asia/Tokyo. Si vous codez en dur une liste de fuseaux horaires, vous créez plusieurs problèmes.

Premièrement, la liste devient obsolète. Les définitions des fuseaux horaires changent lorsque les gouvernements modifient les règles d'heure d'été ou créent de nouveaux fuseaux horaires. Deuxièmement, différents environnements JavaScript prennent en charge différents fuseaux horaires. Un fuseau horaire qui fonctionne dans Chrome pourrait ne pas fonctionner dans un navigateur plus ancien ou une version de Node.js. Troisièmement, maintenir manuellement des centaines de chaînes de caractères de fuseaux horaires crée des opportunités pour des fautes de frappe et des incohérences.

JavaScript fournit la méthode Intl.supportedValuesOf() pour récupérer tous les identifiants de fuseau horaire que l'environnement actuel prend en charge. Cela garantit que votre application n'offre que des fuseaux horaires qui fonctionnent correctement et reste à jour avec les modifications apportées à la base de données des fuseaux horaires.

Ce que sont les identifiants de fuseau horaire

Les identifiants de fuseau horaire sont des chaînes standardisées qui représentent des régions géographiques avec des règles temporelles cohérentes. Ils proviennent de la base de données de fuseaux horaires IANA, une liste complète maintenue par une organisation internationale qui suit les fuseaux horaires et les changements d'heure d'été dans le monde entier.

Les identifiants utilisent un format spécifique qui les rend non ambigus et stables à travers différents systèmes. Comprendre ce format vous aide à travailler efficacement avec les fuseaux horaires.

Comprendre le format des identifiants de fuseau horaire IANA

Les identifiants de fuseau horaire IANA suivent le modèle Area/Location, où l'area représente un continent ou un océan et la location représente une ville ou une région au sein de cette zone.

const examples = [
  'America/New_York',
  'Europe/London',
  'Asia/Tokyo',
  'Australia/Sydney',
  'Pacific/Auckland'
];

L'area correspond à :

  • America pour l'Amérique du Nord et du Sud
  • Europe pour les localisations européennes
  • Asia pour les localisations asiatiques
  • Africa pour les localisations africaines
  • Australia pour les localisations australiennes
  • Pacific pour les îles du Pacifique
  • Atlantic pour les îles de l'Atlantique
  • Indian pour les îles de l'océan Indien
  • Antarctica pour les stations de recherche antarctiques

La location représente généralement la ville la plus grande ou la plus représentative du fuseau horaire. New York représente le fuseau horaire de l'Est des États-Unis. Tokyo représente le Japon. Sydney représente le fuseau horaire de l'Est de l'Australie.

Certains identifiants comprennent trois parties pour les régions au sein d'une zone plus large :

const detailedExamples = [
  'America/Indiana/Indianapolis',
  'America/Kentucky/Louisville',
  'America/North_Dakota/Center'
];

Ces identifiants à plusieurs parties distinguent les régions qui suivent différentes règles temporelles au sein d'un même pays.

La base de données utilise des tirets bas au lieu d'espaces dans les noms de villes :

const underscoreExamples = [
  'America/New_York',    // Pas "New York"
  'America/Los_Angeles', // Pas "Los Angeles"
  'Asia/Ho_Chi_Minh'     // Pas "Ho Chi Minh"
];

Ce format garantit que les identifiants fonctionnent comme des jetons uniques sans caractères spéciaux qui pourraient causer des problèmes d'analyse.

Pourquoi les identifiants utilisent des villes au lieu d'abréviations

Vous pourriez vous attendre à utiliser des abréviations comme EST pour Eastern Standard Time ou PST pour Pacific Standard Time. Cependant, ces abréviations sont ambiguës. EST signifie Eastern Standard Time en Amérique du Nord mais aussi Australian Eastern Standard Time. CST pourrait signifier Central Standard Time, China Standard Time ou Cuba Standard Time.

Les identifiants basés sur les villes restent sans ambiguïté. America/New_York fait toujours référence au même lieu et aux mêmes règles horaires, quel que soit le contexte.

De plus, les abréviations ne tiennent pas compte des transitions d'heure d'été. EST représente uniquement l'heure standard, pas EDT (Eastern Daylight Time). L'identifiant America/New_York gère automatiquement l'heure standard et l'heure d'été en fonction de la date.

Obtenir tous les identifiants de fuseaux horaires pris en charge

La méthode Intl.supportedValuesOf() avec le paramètre 'timeZone' renvoie un tableau de tous les identifiants de fuseaux horaires pris en charge par l'environnement JavaScript.

const timeZones = Intl.supportedValuesOf('timeZone');

console.log(timeZones.length);
// Résultat : plus de 400

console.log(timeZones.slice(0, 10));
// Résultat : [
//   "Africa/Abidjan",
//   "Africa/Accra",
//   "Africa/Addis_Ababa",
//   "Africa/Algiers",
//   "Africa/Asmera",
//   "Africa/Bamako",
//   "Africa/Bangui",
//   "Africa/Banjul",
//   "Africa/Bissau",
//   "Africa/Blantyre"
// ]

La méthode renvoie les identifiants par ordre alphabétique sans doublons. La liste exacte dépend de l'environnement JavaScript, mais les navigateurs modernes et les versions de Node.js prennent en charge plus de 400 fuseaux horaires.

Chaque identifiant du tableau peut être utilisé avec Intl.DateTimeFormat pour formater les dates et heures pour ce fuseau horaire :

const timeZone = timeZones[0]; // "Africa/Abidjan"
const date = new Date('2025-10-15T12:00:00Z');

const formatter = new Intl.DateTimeFormat('en-US', {
  timeZone: timeZone,
  dateStyle: 'long',
  timeStyle: 'short'
});

console.log(formatter.format(date));
// Résultat : "October 15, 2025 at 12:00 PM"

La méthode garantit que chaque identifiant qu'elle renvoie fonctionne correctement avec les API Intl.

Création d'un sélecteur de fuseau horaire

Le cas d'utilisation le plus courant pour obtenir tous les identifiants de fuseau horaire est la création d'un menu déroulant ou d'un élément select permettant aux utilisateurs de choisir leur fuseau horaire.

function buildTimeZoneSelector() {
  const timeZones = Intl.supportedValuesOf('timeZone');
  const select = document.createElement('select');
  select.name = 'timeZone';

  timeZones.forEach(timeZone => {
    const option = document.createElement('option');
    option.value = timeZone;
    option.textContent = timeZone;
    select.appendChild(option);
  });

  return select;
}

const selector = buildTimeZoneSelector();
document.body.appendChild(selector);

Cela crée un élément select avec des options pour chaque fuseau horaire pris en charge. Les utilisateurs peuvent faire défiler la liste et sélectionner leur emplacement.

Cependant, une liste de plus de 400 identifiants non triés crée une expérience utilisateur médiocre. Les utilisateurs doivent comprendre comment les identifiants sont organisés et trouver rapidement leur emplacement.

Regroupement des fuseaux horaires par région

Organiser les fuseaux horaires par continent rend la liste plus facile à naviguer. Vous pouvez extraire la région de chaque identifiant et les regrouper en conséquence.

function groupTimeZonesByRegion() {
  const timeZones = Intl.supportedValuesOf('timeZone');
  const grouped = {};

  timeZones.forEach(timeZone => {
    const parts = timeZone.split('/');
    const region = parts[0];

    if (!grouped[region]) {
      grouped[region] = [];
    }

    grouped[region].push(timeZone);
  });

  return grouped;
}

const grouped = groupTimeZonesByRegion();

console.log(Object.keys(grouped));
// Output: [
//   "Africa", "America", "Antarctica", "Arctic",
//   "Asia", "Atlantic", "Australia", "Europe",
//   "Indian", "Pacific", "Etc"
// ]

console.log(grouped['America'].slice(0, 5));
// Output: [
//   "America/Adak",
//   "America/Anchorage",
//   "America/Anguilla",
//   "America/Antigua",
//   "America/Araguaina"
// ]

La fonction divise chaque identifiant sur la barre oblique et utilise la première partie comme clé de région. Cela crée un objet où chaque région contient un tableau de fuseaux horaires.

Vous pouvez utiliser ces données regroupées pour construire un sélecteur plus organisé avec des éléments optgroup :

function buildGroupedTimeZoneSelector() {
  const grouped = groupTimeZonesByRegion();
  const select = document.createElement('select');
  select.name = 'timeZone';

  Object.keys(grouped).sort().forEach(region => {
    const optgroup = document.createElement('optgroup');
    optgroup.label = region;

    grouped[region].forEach(timeZone => {
      const option = document.createElement('option');
      option.value = timeZone;
      option.textContent = timeZone.split('/').slice(1).join('/');
      optgroup.appendChild(option);
    });

    select.appendChild(optgroup);
  });

  return select;
}

const groupedSelector = buildGroupedTimeZoneSelector();
document.body.appendChild(groupedSelector);

Cela crée un élément select où les fuseaux horaires apparaissent sous leurs rubriques régionales. Le texte de l'option n'affiche que la partie ville de l'identifiant, rendant la liste plus lisible.

Filtrage des fuseaux horaires par région

Parfois, vous n'avez besoin que des fuseaux horaires de régions spécifiques. Par exemple, une application destinée uniquement aux utilisateurs nord-américains pourrait n'afficher que les fuseaux horaires américains.

function getTimeZonesForRegion(region) {
  const timeZones = Intl.supportedValuesOf('timeZone');
  return timeZones.filter(timeZone => timeZone.startsWith(`${region}/`));
}

const americanTimeZones = getTimeZonesForRegion('America');
console.log(americanTimeZones.length);
// Output: plus de 150

console.log(americanTimeZones.slice(0, 5));
// Output: [
//   "America/Adak",
//   "America/Anchorage",
//   "America/Anguilla",
//   "America/Antigua",
//   "America/Araguaina"
// ]

Cette fonction filtre la liste complète pour n'inclure que les identifiants qui commencent par la région spécifiée. Vous pouvez l'appeler avec n'importe quel nom de région pour obtenir une liste ciblée.

Vous pouvez filtrer pour plusieurs régions :

function getTimeZonesForRegions(regions) {
  const timeZones = Intl.supportedValuesOf('timeZone');
  return timeZones.filter(timeZone => {
    return regions.some(region => timeZone.startsWith(`${region}/`));
  });
}

const europeanAndAsianTimeZones = getTimeZonesForRegions(['Europe', 'Asia']);
console.log(europeanAndAsianTimeZones.length);
// Output: plus de 200

Cela offre de la flexibilité pour les applications qui desservent plusieurs régions, mais pas toutes.

Recherche de fuseaux horaires spécifiques

Lorsque les utilisateurs connaissent la ville qu'ils recherchent, la recherche par nom les aide à la trouver rapidement.

function searchTimeZones(query) {
  const timeZones = Intl.supportedValuesOf('timeZone');
  const lowerQuery = query.toLowerCase();

  return timeZones.filter(timeZone => {
    return timeZone.toLowerCase().includes(lowerQuery);
  });
}

const newYorkResults = searchTimeZones('new_york');
console.log(newYorkResults);
// Output: ["America/New_York"]

const londonResults = searchTimeZones('london');
console.log(londonResults);
// Output: ["Europe/London"]

const tokyoResults = searchTimeZones('tokyo');
console.log(tokyoResults);
// Output: ["Asia/Tokyo"]

Cette fonction effectue une recherche insensible à la casse dans tous les identifiants de fuseaux horaires. Les utilisateurs peuvent saisir une partie d'un nom de ville pour trouver les fuseaux horaires correspondants.

Pour une meilleure expérience utilisateur, vous pouvez rechercher des correspondances partielles et gérer les espaces :

function searchTimeZonesFlexible(query) {
  const timeZones = Intl.supportedValuesOf('timeZone');
  const normalizedQuery = query.toLowerCase().replace(/\s+/g, '_');

  return timeZones.filter(timeZone => {
    return timeZone.toLowerCase().includes(normalizedQuery);
  });
}

const results = searchTimeZonesFlexible('new york');
console.log(results);
// Output: ["America/New_York"]

Cette version convertit les espaces dans la requête en traits de soulignement, correspondant au format utilisé dans les identifiants de fuseaux horaires.

Validation des identifiants de fuseau horaire

Lorsque les utilisateurs fournissent des identifiants de fuseau horaire en entrée, vous devez vérifier que l'identifiant est valide avant de l'utiliser avec Intl.DateTimeFormat.

function isValidTimeZone(timeZone) {
  const supportedTimeZones = Intl.supportedValuesOf('timeZone');
  return supportedTimeZones.includes(timeZone);
}

console.log(isValidTimeZone('America/New_York'));
// Résultat: true

console.log(isValidTimeZone('Europe/London'));
// Résultat: true

console.log(isValidTimeZone('Invalid/TimeZone'));
// Résultat: false

console.log(isValidTimeZone('EST'));
// Résultat: false

Cette fonction vérifie si une chaîne donnée apparaît dans la liste des fuseaux horaires pris en charge. Si l'identifiant est invalide, vous pouvez le rejeter ou demander à l'utilisateur de choisir parmi les options valides.

Vous pouvez également essayer d'utiliser l'identifiant et capturer les erreurs :

function validateTimeZoneByCatch(timeZone) {
  try {
    new Intl.DateTimeFormat('en-US', { timeZone });
    return true;
  } catch (error) {
    return false;
  }
}

console.log(validateTimeZoneByCatch('America/New_York'));
// Résultat: true

console.log(validateTimeZoneByCatch('Invalid/TimeZone'));
// Résultat: false

Cette approche fonctionne mais est moins efficace que la vérification de la liste des valeurs prises en charge. Utilisez la vérification des valeurs prises en charge lorsque la performance est importante.

Affichage des décalages actuels pour les fuseaux horaires

Les utilisateurs pensent souvent aux fuseaux horaires en termes de décalage par rapport à UTC. Afficher le décalage actuel à côté de chaque nom de fuseau horaire aide les utilisateurs à comprendre la différence de temps.

function getTimeZoneOffset(timeZone) {
  const date = new Date();
  const formatter = new Intl.DateTimeFormat('en-US', {
    timeZone,
    timeZoneName: 'shortOffset'
  });

  const parts = formatter.formatToParts(date);
  const offsetPart = parts.find(part => part.type === 'timeZoneName');

  return offsetPart ? offsetPart.value : '';
}

const timeZones = [
  'America/New_York',
  'Europe/London',
  'Asia/Tokyo',
  'Australia/Sydney'
];

timeZones.forEach(timeZone => {
  const offset = getTimeZoneOffset(timeZone);
  console.log(`${timeZone}: ${offset}`);
});

// Résultat :
// America/New_York: GMT-4
// Europe/London: GMT+1
// Asia/Tokyo: GMT+9
// Australia/Sydney: GMT+11

La fonction formate une date avec le style de nom de fuseau horaire shortOffset, puis extrait la partie décalage des éléments formatés. Cela montre combien d'heures d'avance ou de retard chaque fuseau horaire a par rapport à UTC.

Notez que les décalages changent avec l'heure d'été. Le même fuseau horaire affiche des décalages différents en hiver et en été :

const newYorkWinter = getTimeZoneOffset('America/New_York');
// En janvier : GMT-5

const newYorkSummer = getTimeZoneOffset('America/New_York');
// En juillet : GMT-4

Le décalage renvoyé par cette fonction reflète la date actuelle, il se met donc automatiquement à jour lorsque les règles d'heure d'été changent tout au long de l'année.

Construction d'un sélecteur de fuseau horaire complet avec décalages

La combinaison du regroupement, du filtrage et de l'affichage des décalages crée un sélecteur de fuseau horaire complet :

function buildCompleteTimeZoneSelector() {
  const timeZones = Intl.supportedValuesOf('timeZone');
  const select = document.createElement('select');
  select.name = 'timeZone';

  const grouped = {};
  timeZones.forEach(timeZone => {
    const region = timeZone.split('/')[0];
    if (!grouped[region]) {
      grouped[region] = [];
    }
    grouped[region].push(timeZone);
  });

  Object.keys(grouped).sort().forEach(region => {
    const optgroup = document.createElement('optgroup');
    optgroup.label = region;

    grouped[region].forEach(timeZone => {
      const offset = getTimeZoneOffset(timeZone);
      const location = timeZone.split('/').slice(1).join('/');

      const option = document.createElement('option');
      option.value = timeZone;
      option.textContent = `${location} (${offset})`;
      optgroup.appendChild(option);
    });

    select.appendChild(optgroup);
  });

  return select;
}

const completeSelector = buildCompleteTimeZoneSelector();
document.body.appendChild(completeSelector);

Ce sélecteur regroupe les fuseaux horaires par région, affiche des noms de lieux lisibles et inclut les décalages UTC actuels. Les utilisateurs peuvent rapidement trouver leur fuseau horaire par région et vérifier que le décalage correspond à leurs attentes.

Obtention du fuseau horaire actuel de l'utilisateur

Bien que l'obtention de tous les fuseaux horaires pris en charge soit utile pour les interfaces de sélection, vous souhaitez souvent connaître le fuseau horaire actuel de l'utilisateur pour l'utiliser comme valeur par défaut.

function getUserTimeZone() {
  return Intl.DateTimeFormat().resolvedOptions().timeZone;
}

const userTimeZone = getUserTimeZone();
console.log(userTimeZone);
// Sortie : "America/New_York" (ou le fuseau horaire réel de l'utilisateur)

Cela renvoie l'identifiant IANA du fuseau horaire système de l'utilisateur. Vous pouvez l'utiliser pour présélectionner l'option correcte dans un sélecteur de fuseau horaire :

function buildTimeZoneSelectorWithDefault() {
  const selector = buildCompleteTimeZoneSelector();
  const userTimeZone = getUserTimeZone();

  const options = selector.querySelectorAll('option');
  options.forEach(option => {
    if (option.value === userTimeZone) {
      option.selected = true;
    }
  });

  return selector;
}

const selectorWithDefault = buildTimeZoneSelectorWithDefault();
document.body.appendChild(selectorWithDefault);

Cela crée un sélecteur avec le fuseau horaire actuel de l'utilisateur déjà sélectionné, réduisant ainsi les frictions lorsque les utilisateurs confirment leur emplacement.

Gestion des fuseaux horaires spéciaux

La liste des fuseaux horaires pris en charge comprend certains identifiants spéciaux qui ne suivent pas le modèle standard Zone/Emplacement.

const timeZones = Intl.supportedValuesOf('timeZone');

const specialTimeZones = timeZones.filter(tz => !tz.includes('/'));
console.log(specialTimeZones);
// Résultat : ["UTC"]

L'identifiant UTC représente le Temps Universel Coordonné, qui n'a pas de décalage et pas de changements d'heure d'été. Cet identifiant est utile lorsque vous souhaitez afficher des heures dans un référentiel universel plutôt que dans un fuseau horaire local.

Certains environnements incluent des identifiants spéciaux supplémentaires comme GMT ou des décalages de zone comme Etc/GMT+5. Vous pouvez les filtrer si votre application n'a besoin que de fuseaux horaires géographiques standard :

function getGeographicTimeZones() {
  const timeZones = Intl.supportedValuesOf('timeZone');
  return timeZones.filter(timeZone => {
    return timeZone.includes('/') && !timeZone.startsWith('Etc/');
  });
}

const geographicTimeZones = getGeographicTimeZones();
console.log(geographicTimeZones.length);
// Résultat : plus de 400

Cela filtre les identifiants non géographiques, ne laissant que les fuseaux horaires standard basés sur les villes.

Comprendre les alias de fuseaux horaires

La base de données IANA inclut plusieurs identifiants qui font référence aux mêmes règles de fuseau horaire. Par exemple, Asia/Calcutta et Asia/Kolkata font tous deux référence à l'heure normale de l'Inde, mais Kolkata est le nom moderne.

La méthode Intl.supportedValuesOf() renvoie les identifiants canoniques. Si les utilisateurs fournissent un alias, il fonctionne toujours avec Intl.DateTimeFormat :

const canonicalFormatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'Asia/Kolkata',
  timeZoneName: 'long'
});

const aliasFormatter = new Intl.DateTimeFormat('en-US', {
  timeZone: 'Asia/Calcutta',
  timeZoneName: 'long'
});

const date = new Date('2025-10-15T12:00:00Z');

console.log(canonicalFormatter.format(date));
// Résultat : heure en heure normale de l'Inde

console.log(aliasFormatter.format(date));
// Résultat : heure en heure normale de l'Inde

Les deux formateurs produisent le même résultat car l'alias est mappé à l'identifiant canonique en interne.

Cependant, la liste des valeurs prises en charge n'inclut que les identifiants canoniques. Si vous validez les entrées utilisateur, envisagez de normaliser les alias vers leurs formes canoniques :

function normalizeTimeZone(timeZone) {
  try {
    const formatter = new Intl.DateTimeFormat('en-US', { timeZone });
    return formatter.resolvedOptions().timeZone;
  } catch (error) {
    return null;
  }
}

console.log(normalizeTimeZone('Asia/Calcutta'));
// Résultat : "Asia/Kolkata"

console.log(normalizeTimeZone('America/New_York'));
// Résultat : "America/New_York"

console.log(normalizeTimeZone('Invalid/Zone'));
// Résultat : null

Cette fonction crée un formateur avec le fuseau horaire fourni et extrait l'identifiant canonique des options résolues. Si l'identifiant est invalide, le formateur génère une erreur et la fonction renvoie null.

Prise en charge et compatibilité des navigateurs

La méthode Intl.supportedValuesOf() est disponible dans les navigateurs modernes et les versions de Node.js :

  • Chrome 99 et versions ultérieures
  • Firefox 93 et versions ultérieures
  • Safari 15.4 et versions ultérieures
  • Edge 99 et versions ultérieures
  • Node.js 18.0.0 et versions ultérieures

Pour les environnements plus anciens, vous pouvez détecter la disponibilité de cette méthode et fournir une solution de repli :

function getSupportedTimeZones() {
  if (typeof Intl.supportedValuesOf === 'function') {
    return Intl.supportedValuesOf('timeZone');
  }

  return [
    'Africa/Cairo',
    'America/New_York',
    'America/Chicago',
    'America/Denver',
    'America/Los_Angeles',
    'Asia/Dubai',
    'Asia/Kolkata',
    'Asia/Tokyo',
    'Australia/Sydney',
    'Europe/London',
    'Europe/Paris',
    'Pacific/Auckland',
    'UTC'
  ];
}

const timeZones = getSupportedTimeZones();

Cette fonction vérifie si Intl.supportedValuesOf existe et renvoie la liste complète si disponible. Sinon, elle renvoie une liste prédéfinie plus restreinte de fuseaux horaires courants. Cette solution de repli garantit que votre application fonctionne dans les environnements plus anciens tout en fournissant la liste complète dans les environnements modernes.