Comment obtenir la liste des identifiants de fuseau horaire valides

Récupérer tous les identifiants de fuseau horaire IANA pris en charge en JavaScript pour créer des listes déroulantes et valider les saisies utilisateur

Introduction

Lors de la création de fonctionnalités permettant aux utilisateurs de sélectionner leur fuseau horaire, vous devez savoir quels identifiants de fuseau horaire sont valides. Un utilisateur à New York pourrait avoir besoin de choisir America/New_York, tandis qu'un utilisateur à Tokyo a 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 de fuseau horaire 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 fuseau horaire crée des opportunités de fautes de frappe et d'incohérences.

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

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 horaires cohérentes. Ils proviennent de la base de données des 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 sur 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ù la zone représente un continent ou un océan et l'emplacement 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'
];

La zone correspond à :

  • America pour l'Amérique du Nord et du Sud
  • Europe pour les emplacements européens
  • Asia pour les emplacements asiatiques
  • Africa pour les emplacements africains
  • Australia pour les emplacements australiens
  • 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

L'emplacement 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 en plusieurs parties distinguent les régions qui suivent des règles horaires différentes au sein d'un même pays.

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

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

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

Pourquoi les identifiants utilisent des villes plutôt que des 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 non ambigus. 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 capturent pas les transitions d'heure d'été. EST représente uniquement l'heure standard, et non 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);
// Output: over 400

console.log(timeZones.slice(0, 10));
// Output: [
//   "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 de 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));
// Output: "October 15, 2025 at 12:00 PM"

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

Créer un sélecteur de fuseau horaire

Le cas d'usage le plus courant pour obtenir tous les identifiants de fuseaux horaires est de créer un menu déroulant ou 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 parcourir la liste et sélectionner leur emplacement.

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

Regrouper les fuseaux horaires par région

Organiser les fuseaux horaires par continent facilite la navigation dans la liste. 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 groupé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 en-têtes régionaux. Le texte de l'option affiche uniquement la partie ville de l'identifiant, rendant la liste plus lisible.

Filtrer les 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: over 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 inclure uniquement 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: over 200

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

Rechercher des 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 sur 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.

Valider les identifiants de fuseaux horaires

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'));
// Output: true

console.log(isValidTimeZone('Europe/London'));
// Output: true

console.log(isValidTimeZone('Invalid/TimeZone'));
// Output: false

console.log(isValidTimeZone('EST'));
// Output: 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 n'est pas valide, vous pouvez le rejeter ou inviter l'utilisateur à choisir parmi les options valides.

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

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

console.log(validateTimeZoneByCatch('America/New_York'));
// Output: true

console.log(validateTimeZoneByCatch('Invalid/TimeZone'));
// Output: 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 les performances sont importantes.

Afficher les décalages actuels pour les fuseaux horaires

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

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}`);
});

// Output:
// 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 parties formatées. Cela montre de combien d'heures chaque fuseau horaire est en avance ou en retard par rapport à l'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');
// In January: GMT-5

const newYorkSummer = getTimeZoneOffset('America/New_York');
// In July: GMT-4

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

Créer 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.

Obtenir le fuseau horaire actuel de l'utilisateur

Bien qu'obtenir 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 par défaut.

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

const userTimeZone = getUserTimeZone();
console.log(userTimeZone);
// Output: "America/New_York" (or user's actual time zone)

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

Gérer les fuseaux horaires spéciaux

La liste des fuseaux horaires pris en charge inclut certains identifiants spéciaux qui ne suivent pas le modèle standard Area/Location.

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

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

L'identifiant UTC représente le temps universel coordonné, qui n'a pas de décalage et aucun changement d'heure d'été. Cet identifiant est utile lorsque vous souhaitez afficher les 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 des 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);
// Output: over 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 standard indienne, mais Kolkata est le nom moderne.

La méthode Intl.supportedValuesOf() renvoie les identifiants canoniques. Si les utilisateurs fournissent un alias, cela 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));
// Output: time in Indian Standard Time

console.log(aliasFormatter.format(date));
// Output: time in Indian Standard Time

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

Cependant, la liste des valeurs prises en charge inclut uniquement les identifiants canoniques. Si vous validez une entrée 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'));
// Output: "Asia/Kolkata"

console.log(normalizeTimeZone('America/New_York'));
// Output: "America/New_York"

console.log(normalizeTimeZone('Invalid/Zone'));
// Output: 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 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 fonctionnalité 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 codée en dur plus petite de fuseaux horaires courants. La solution de repli garantit que votre application fonctionne dans les environnements plus anciens tout en fournissant la liste complète dans les environnements modernes.