Comment formater les dates dans différents fuseaux horaires
Affichez les dates et heures pour n'importe quel fuseau horaire en utilisant l'API Intl.DateTimeFormat de JavaScript
Introduction
Le même instant dans le temps s'affiche sous forme d'heures différentes à travers le monde. Lorsqu'une réunion commence à 15h00 à New York, les horloges à Londres affichent 20h00 et les horloges à Tokyo affichent 5h00 le lendemain. Si votre application affiche les heures sans tenir compte des fuseaux horaires, les utilisateurs voient des informations incorrectes.
Un utilisateur en Californie réservant un vol qui décolle à 14h00 s'attend à voir 14h00 affiché. Si votre application formate toutes les heures en utilisant le fuseau horaire du serveur en Virginie, l'utilisateur voit 17h00 et arrive à l'aéroport trois heures en retard. Cette confusion se multiplie pour chaque heure affichée dans votre application.
L'API Intl.DateTimeFormat de JavaScript fournit l'option timeZone pour formater les dates et heures pour n'importe quel fuseau horaire. Cette leçon explique pourquoi les fuseaux horaires existent, comment JavaScript les gère en interne, et comment formater correctement les dates pour les utilisateurs partout dans le monde.
Pourquoi les fuseaux horaires existent
La Terre tourne, créant le jour et la nuit à différents endroits à différents moments. Lorsque le soleil est au zénith à New York, il s'est déjà couché à Londres et ne s'est pas encore levé à Tokyo. Chaque lieu connaît midi à un moment différent.
Avant la standardisation des fuseaux horaires, chaque ville gardait son propre temps local basé sur la position du soleil. Cela créait des problèmes pour les chemins de fer et les télégraphes qui reliaient des villes éloignées. En 1884, les pays ont convenu de diviser le monde en fuseaux horaires, chacun d'environ 15 degrés de longitude de large, correspondant à une heure de rotation de la Terre.
Chaque fuseau horaire a un décalage standard par rapport au temps universel coordonné, abrégé UTC. New York utilise UTC-5 ou UTC-4 selon l'heure d'été. Londres utilise UTC+0 ou UTC+1. Tokyo utilise UTC+9 toute l'année.
Lorsque vous affichez des heures aux utilisateurs, vous devez convertir le moment universel en heure locale qu'ils s'attendent à voir.
Comment JavaScript stocke les heures en interne
Les objets Date de JavaScript représentent un moment unique dans le temps sous forme de nombre de millisecondes depuis le 1er janvier 1970 à minuit UTC. Cette représentation interne n'a pas de fuseau horaire.
const date = new Date('2025-03-15T20:00:00Z');
console.log(date.getTime());
// Output: 1742331600000
Le Z à la fin de la chaîne ISO indique l'heure UTC. L'objet Date stocke l'horodatage 1742331600000, qui représente le même moment pour tout le monde dans le monde, quel que soit leur fuseau horaire.
Lorsque vous appelez des méthodes comme toString() sur un objet Date, JavaScript convertit l'horodatage UTC en votre fuseau horaire local pour l'affichage. Cette conversion automatique peut créer de la confusion lorsque vous souhaitez afficher des heures pour un fuseau horaire différent.
L'API Intl.DateTimeFormat avec l'option timeZone vous donne un contrôle explicite sur le fuseau horaire à utiliser pour le formatage.
Utilisation de l'option timeZone
L'option timeZone spécifie le fuseau horaire à utiliser lors du formatage d'une date. Passez l'option dans l'objet d'options lors de la création d'un formateur.
const date = new Date('2025-03-15T20:00:00Z');
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/New_York',
dateStyle: 'short',
timeStyle: 'short'
});
console.log(formatter.format(date));
// Output: "3/15/25, 3:00 PM"
La date représente 20h00 UTC. New York est UTC-5 pendant l'heure standard ou UTC-4 pendant l'heure d'été. En mars, l'heure d'été est active, donc New York est UTC-4. Le formateur convertit 20h00 UTC en 16h00 heure locale, mais l'exemple montre 15h00, ce qui suggère qu'il s'agit de l'heure standard dans ce scénario spécifique.
Le formateur gère la conversion automatiquement. Vous fournissez le moment UTC et le fuseau horaire cible, et l'API produit l'heure locale correcte.
Comprendre les noms de fuseaux horaires IANA
L'option timeZone accepte les identifiants de fuseaux horaires de la base de données IANA Time Zone Database. Ces identifiants utilisent le format Region/City, tels que America/New_York, Europe/London ou Asia/Tokyo.
const date = new Date('2025-03-15T20:00:00Z');
const zones = [
'America/New_York',
'Europe/London',
'Asia/Tokyo',
'Australia/Sydney'
];
zones.forEach(zone => {
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: zone,
dateStyle: 'short',
timeStyle: 'long'
});
console.log(`${zone}: ${formatter.format(date)}`);
});
// Output:
// America/New_York: 3/15/25, 4:00:00 PM EDT
// Europe/London: 3/15/25, 8:00:00 PM GMT
// Asia/Tokyo: 3/16/25, 5:00:00 AM JST
// Australia/Sydney: 3/16/25, 7:00:00 AM AEDT
Chaque fuseau horaire affiche une heure locale différente pour le même instant. New York affiche 16h00 le 15 mars. Londres affiche 20h00 le 15 mars. Tokyo et Sydney sont déjà passés au 16 mars, affichant respectivement 5h00 et 7h00.
Les noms IANA gèrent automatiquement l'heure d'été. Le formateur sait que America/New_York bascule entre l'heure normale de l'Est et l'heure d'été de l'Est et applique le décalage correct pour n'importe quelle date.
Trouver des noms de fuseaux horaires IANA valides
La base de données IANA contient plusieurs centaines d'identifiants de fuseaux horaires. Les modèles courants incluent :
America/New_Yorkpour New YorkAmerica/Los_Angelespour Los AngelesAmerica/Chicagopour ChicagoEurope/Londonpour LondresEurope/Parispour ParisEurope/Berlinpour BerlinAsia/Tokyopour TokyoAsia/Shanghaipour ShanghaiAsia/Kolkatapour l'IndeAustralia/Sydneypour SydneyPacific/Aucklandpour Auckland
Les identifiants utilisent des noms de villes plutôt que des abréviations de fuseaux horaires comme EST ou PST car les abréviations sont ambiguës. EST signifie Eastern Standard Time en Amérique du Nord mais aussi Australian Eastern Standard Time. Les noms basés sur les villes restent sans ambiguïté.
Vous pouvez rechercher la liste complète des identifiants dans la documentation de la base de données des fuseaux horaires IANA.
Utiliser UTC comme fuseau horaire
L'identifiant spécial UTC formate les dates en temps universel coordonné, qui n'a aucun décalage par rapport au méridien de Greenwich.
const date = new Date('2025-03-15T20:00:00Z');
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'UTC',
dateStyle: 'short',
timeStyle: 'long'
});
console.log(formatter.format(date));
// Output: "3/15/25, 8:00:00 PM UTC"
L'heure UTC correspond à l'horodatage interne stocké dans l'objet Date. Utiliser UTC pour le formatage est utile lors de l'affichage d'heures qui ne doivent pas changer en fonction de la localisation de l'utilisateur, comme les journaux de serveur ou les horodatages de base de données.
Obtenir le fuseau horaire de l'utilisateur
La méthode resolvedOptions() renvoie les options réelles utilisées par un formateur, y compris le fuseau horaire. Lorsque vous créez un formateur sans spécifier timeZone, il utilise par défaut le fuseau horaire système de l'utilisateur.
const formatter = new Intl.DateTimeFormat();
const options = formatter.resolvedOptions();
console.log(options.timeZone);
// Output: "America/New_York" (or user's actual time zone)
Cela vous donne l'identifiant IANA du fuseau horaire actuel de l'utilisateur. Vous pouvez utiliser cet identifiant pour formater d'autres dates dans le même fuseau ou pour stocker la préférence de fuseau horaire de l'utilisateur.
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: userTimeZone,
dateStyle: 'full',
timeStyle: 'long'
});
const date = new Date('2025-03-15T20:00:00Z');
console.log(formatter.format(date));
// Output varies based on user's time zone
Ce modèle garantit que les dates s'affichent automatiquement dans l'heure locale de l'utilisateur.
Formater le même instant pour plusieurs fuseaux horaires
Vous pouvez formater le même objet Date pour plusieurs fuseaux horaires afin de montrer aux utilisateurs à quelle heure un événement se produit dans différents lieux.
const meetingTime = new Date('2025-03-15T20:00:00Z');
const zones = [
{ name: 'New York', zone: 'America/New_York' },
{ name: 'London', zone: 'Europe/London' },
{ name: 'Tokyo', zone: 'Asia/Tokyo' }
];
zones.forEach(({ name, zone }) => {
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: zone,
dateStyle: 'long',
timeStyle: 'short'
});
console.log(`${name}: ${formatter.format(meetingTime)}`);
});
// Output:
// New York: March 15, 2025 at 4:00 PM
// London: March 15, 2025 at 8:00 PM
// Tokyo: March 16, 2025 at 5:00 AM
Cela aide les utilisateurs à comprendre quand une réunion ou un événement se produit dans leur fuseau horaire et dans les fuseaux horaires des autres participants.
Formater des dates sans heures à travers les fuseaux horaires
Lors du formatage de dates sans heures, le fuseau horaire peut affecter la date calendaire qui apparaît. Une date à minuit UTC tombe sur différentes dates calendaires dans différents fuseaux horaires.
const date = new Date('2025-03-16T01:00:00Z');
const formatter1 = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/Los_Angeles',
dateStyle: 'long'
});
const formatter2 = new Intl.DateTimeFormat('en-US', {
timeZone: 'Asia/Tokyo',
dateStyle: 'long'
});
console.log(`Los Angeles: ${formatter1.format(date)}`);
console.log(`Tokyo: ${formatter2.format(date)}`);
// Output:
// Los Angeles: March 15, 2025
// Tokyo: March 16, 2025
Le moment 1:00 AM UTC du 16 mars correspond à 5:00 PM le 15 mars à Los Angeles et 10:00 AM le 16 mars à Tokyo. La date calendaire diffère d'un jour entre les deux fuseaux horaires.
Cela importe lors de l'affichage de dates pour des événements planifiés, des échéances, ou toute date que les utilisateurs interprètent par rapport à leur calendrier local.
Utilisation des décalages de fuseau horaire
Au lieu des identifiants IANA, vous pouvez utiliser des chaînes de décalage comme +01:00 ou -05:00. Celles-ci représentent des décalages fixes par rapport à UTC.
const date = new Date('2025-03-15T20:00:00Z');
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: '+09:00',
dateStyle: 'short',
timeStyle: 'long'
});
console.log(formatter.format(date));
// Output: "3/16/25, 5:00:00 AM GMT+9"
Les chaînes de décalage fonctionnent lorsque vous connaissez le décalage exact mais pas l'emplacement spécifique. Cependant, elles ne gèrent pas l'heure d'été. Si vous utilisez -05:00 pour représenter New York, les heures seront incorrectes pendant l'heure d'été lorsque New York utilise en réalité -04:00.
Les identifiants IANA sont préférés car ils gèrent automatiquement l'heure d'été.
Comprendre le fonctionnement de l'heure d'été
De nombreuses régions changent leur décalage horaire deux fois par an pour l'heure d'été. Au printemps, les horloges avancent d'une heure. En automne, les horloges reculent d'une heure. Cela signifie que le décalage UTC pour un emplacement change tout au long de l'année.
Lorsque vous utilisez des identifiants de fuseau horaire IANA, l'API Intl.DateTimeFormat applique automatiquement le décalage correct pour toute date.
const winterDate = new Date('2025-01-15T20:00:00Z');
const summerDate = new Date('2025-07-15T20:00:00Z');
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'America/New_York',
dateStyle: 'long',
timeStyle: 'long'
});
console.log(`Winter: ${formatter.format(winterDate)}`);
console.log(`Summer: ${formatter.format(summerDate)}`);
// Output:
// Winter: January 15, 2025 at 3:00:00 PM EST
// Summer: July 15, 2025 at 4:00:00 PM EDT
En janvier, New York utilise l'heure normale de l'Est avec un décalage UTC-5, affichant 3:00 PM. En juillet, New York utilise l'heure d'été de l'Est avec un décalage UTC-4, affichant 4:00 PM. Le même moment UTC produit des heures locales différentes selon que l'heure d'été est active ou non.
Vous n'avez pas besoin de suivre quelles dates utilisent quel décalage. L'API gère cela automatiquement.
Formatage des heures pour la planification d'événements
Lors de l'affichage des heures d'événements, formatez l'heure dans le lieu de l'événement et éventuellement dans le lieu de l'utilisateur.
const eventTime = new Date('2025-03-15T18:00:00Z');
const eventTimeZone = 'Europe/Paris';
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const eventFormatter = new Intl.DateTimeFormat('en-US', {
timeZone: eventTimeZone,
dateStyle: 'full',
timeStyle: 'short'
});
const userFormatter = new Intl.DateTimeFormat('en-US', {
timeZone: userTimeZone,
dateStyle: 'full',
timeStyle: 'short'
});
console.log(`Event time: ${eventFormatter.format(eventTime)} (Paris)`);
console.log(`Your time: ${userFormatter.format(eventTime)}`);
// Output (for a user in New York):
// Event time: Saturday, March 15, 2025 at 7:00 PM (Paris)
// Your time: Saturday, March 15, 2025 at 2:00 PM
Ce modèle montre aux utilisateurs à la fois quand l'événement se produit dans son propre fuseau horaire et quand ils doivent se joindre en fonction de leur emplacement.
Formatage des horodatages serveur dans le fuseau horaire de l'utilisateur
Les journaux serveur et les enregistrements de base de données utilisent souvent des horodatages UTC. Lors de leur affichage aux utilisateurs, convertissez-les dans le fuseau horaire local de l'utilisateur.
const serverTimestamp = new Date('2025-03-15T20:00:00Z');
const userTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
const formatter = new Intl.DateTimeFormat(navigator.language, {
timeZone: userTimeZone,
dateStyle: 'short',
timeStyle: 'medium'
});
console.log(`Activity: ${formatter.format(serverTimestamp)}`);
// Output varies based on user's time zone and locale
// For en-US in New York: "Activity: 3/15/25, 4:00:00 PM"
Cela garantit que les utilisateurs voient les horodatages dans l'heure locale familière plutôt qu'en UTC ou en heure serveur.
Combinaison de timeZone avec d'autres options
L'option timeZone fonctionne avec toutes les autres options Intl.DateTimeFormat. Vous pouvez spécifier des composants de date et d'heure individuels, utiliser des préréglages de style ou contrôler le système de calendrier.
const date = new Date('2025-03-15T20:00:00Z');
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'Asia/Tokyo',
weekday: 'long',
year: 'numeric',
month: 'long',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZoneName: 'long'
});
console.log(formatter.format(date));
// Output: "Monday, March 16, 2025 at 5:00:00 AM Japan Standard Time"
L'option timeZoneName contrôle la façon dont le nom du fuseau horaire apparaît dans la sortie. Les leçons ultérieures couvriront cette option en détail.
Ce qu'il faut éviter
N'utilisez pas d'abréviations de fuseaux horaires comme EST, PST ou GMT comme valeurs pour l'option timeZone. Ces abréviations sont ambiguës et ne sont pas prises en charge de manière cohérente.
// Incorrect - abbreviations may not work
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'EST', // This may throw an error
dateStyle: 'short',
timeStyle: 'short'
});
Utilisez toujours des identifiants IANA comme America/New_York ou des chaînes de décalage comme -05:00.
Ne supposez pas que le fuseau horaire de l'utilisateur correspond au fuseau horaire du serveur. Formatez toujours les heures explicitement dans la zone correcte ou utilisez le fuseau horaire détecté de l'utilisateur.
Réutilisation des formateurs entre fuseaux horaires
Lors du formatage de dates pour plusieurs fuseaux horaires, vous pourriez créer de nombreux formateurs. Si vous formatez de nombreuses dates avec les mêmes paramètres, réutilisez les instances de formateur pour de meilleures performances.
const dates = [
new Date('2025-03-15T20:00:00Z'),
new Date('2025-03-16T14:00:00Z'),
new Date('2025-03-17T09:00:00Z')
];
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: 'Europe/Berlin',
dateStyle: 'short',
timeStyle: 'short'
});
dates.forEach(date => {
console.log(formatter.format(date));
});
// Output:
// "3/15/25, 9:00 PM"
// "3/16/25, 3:00 PM"
// "3/17/25, 10:00 AM"
La création d'un formateur implique le traitement des options et le chargement des données de locale. Réutiliser le même formateur pour plusieurs dates évite cette surcharge.