Calculer le décalage horaire d’une date à partir du fuseau horaire

Problématique

Nous avons vu précédemment que nativement, il n’est pas possible en javascript de créer des dates autrement que dans le fuseau horaire du navigateur (qui est donné par l’OS sous-jacent) ou en temps UTC.

Si l’on veut créer une date (complète, c'est-à-dire précisant aussi l’heure) dans un autre fuseau horaire, il est possible de le faire en précisant l’offset de ce fuseau horaire par rapport au temps UTC.

Ainsi, si la variable utc contient une date UTC.

On commence par convertir la date UTC en millisecondes (via l’api getTime() qui donne le nombre de millisecondes depuis le 1er janvier 1970).

// la date UTC (en ms)
var utc = maDateUTC.getTime() ;

avec la variable timeZoneOffset qui contient l’offset de la zone horaire exprimé en minutes.

On convertit le timeZoneOffset en millisecondes (il y a 60000 ms dans 1 minute) :

// l’offset en millisecondes
var msOffset=timeZoneOffset * 60000 ;

myDate, qui contient la conversion en UTC, est construite à partir du nombre de millisecondes total

var msLocal=utc+msOffset ;
var myDate=new Date(msLocal) ;

Rappelons que l’api getTimeZoneOffset, rend le nombre de minutes (positif ou négatif) de décalage du temps local du navigateur par rapport à UTC.

En parsant une date au format ISO 8601 (par exemple 2010-07-16T19:20:30,4+01:00) et en convertissant le décalage horaire associé et en s’inspirant du code précédent, il est donc possible de convertir en UTC une date dont on connaît le décalage horaire.

Déterminer le décalage horaire d’une date en fonction de la zone horaire

Être capable de convertir en UTC une date dont on connaît le décalage horaire, c’est bien. Être capable de déterminer ce décalage horaire à partir d’un fuseau horaire, c’est mieux ! Ce décalage horaire n’est généralement pas fixe puisqu’il dépend du décalage heure d’été/heure d’hiver. Il est donc nécessaire de déterminer, pour la zone horaire considérée, si la date qu’on souhaite créer est en horaire d’été ou d’hiver et le décalage horaire associé.

La tz database

Nous avions fait allusion aux tables de la tz database qui sont très utilisées. Cette base indique les modifications des zones horaires (y compris les changements d’horaire saisonnier) aussi bien passées que futures (dans les limites où il est possible de l’anticiper ; par exemple, au Brésil, le changement d’horaire saisonnier est fixé par décret).

La tz database est maintenue par des volontaires. Les commentaires des fichiers sources de la base donnent une indication de la difficulté pour rassembler ces informations, surtout pour les périodes historiques (ne serait ce que pour avoir les décalages horaires en France durant la dernière guerre suite au découpage en zone occupée/zone libre).

Dans la tz database, une zone horaire (ou time zone pour les anglo-saxons), est une zone géographique qui depuis 1970 est synchronisée en terme d’heure locale (y compris vis-à-vis des changements saisonniers). Cette zone géographique peut comporter plusieurs pays ou une région sous-nationale pour les certains pays étendus.

La tz database définit des conventions de nommage du type région/lieu (où région représente un continent, un océan ou la valeur spéciale Etc) pour l’identification unique des zones horaires (zone name). Cela donne par exemple America/New_York et Europe/Paris. Ces conventions utilisent les noms anglo-saxons (et pas locaux) et interdisent le caractère espace (au profit du tiret et du underscore). Dans certains cas, le lieu lui-même peut être composite (ce qui donne par exemple America/Indiana/Indianapolis).

La liste des idenfiants de zone horaire est disponible dans le fichier zone.tab à ftp://elsie.nci.nih.gov/pub/ . Par exemple la dernière version est contenue dans le fichier tzdata2010j.tar.gz. Ce fichier comporte pour chaque ligne (l’espace servant de séparateur) :

  • le code 2 caractères du pays (ISO 3166),
  • la latitude et longitude du lieu (en ISO 6709),
  • l’identifiant unique (zone name) et éventuellement des commentaires.

Voilà par exemple un extrait de zone.tab (les deux premières lignes comportent un commentaire) :

FM +0725+15147 Pacific/Truk Truk (Chuuk) and Yap
FM +0658+15813 Pacific/Ponape Ponape (Pohnpei)
FM +0519+16259 Pacific/Kosrae Kosrae
FO +6201-00646 Atlantic/Faroe
FR +4852+00220 Europe/Paris
GA +0023+00927 Africa/Libreville
GB +513030-0000731 Europe/London
GD +1203-06145 America/Grenada
GE +4143+04449 Asia/Tbilisi

Grâce à ces identifiants, un utilisateur peut donc choisir la zone horaire qu’il lui convient (et n’a donc plus à manipuler directement le décalage horaire par rapport à UTC).

Noter que Microsoft utilise d’autres conventions dans windows et qu’il existe une table de conversion des identifiants de zone horaire de windows à la tz database.. Pour ceux qui sont intéressés par les arcanes de la gestion des fuseaux horaires sous windows, voir l’article.

Utiliser les fichiers de la tz database

Il est bien sûr possible de parser les fichiers sources de la tz_database mais ils existent sous plusieurs forme compilées à http://code.google.com/p/tzdata/.

Le ficher tzdata_latest_all.zip disponible à cette adresse comporte en effet les formes compilées csv (excel), js, json, php, ruby et xml.

Par exemple, dans le sous-répertoire js/Europe figure le fichier paris.js. dont voilà un extrait :

{
"from": 1288486800000, // 2010-10-31T01:00:00Z
"to": 1301187600000, // 2011-03-27T01:00:00Z
"dst": false,
"offset": 3600,
"name": "CET"
}

Les propriétés de cette structure sont les suivantes :

  • from décrit (en millisecondes) la date à partir de laquelle l’offset s’applique (dans le fragment précédent, çà donne le 31 octobre à 1h en UTC).
  • to décrit (en millisecondes) la date jusqu’à laquelle l’offset s’applique (dans le fragment précédent, çà donne le 27 mars à 1h en UTC).
  • dst est un booléen à vrai si on est en heure d’été.
  • offset est le décalage horaire (en secondes) par rapport à l’UTC (dans le fragment précédent, on a dans cette période un décalage horaire de 3600 secondes, c'est-à-dire 1 heure)
  • name est le nom courant décrivant ce décalage horaire.

Dans le tableau suivant figure la liste des names utilisés en eurore (ce tableau est disponible dans le fichier source de la tz database décrivant l’europe) :

  • La première colonne donne le décalage horaire de l’heure d’hiver par rapport à l’UTC.
  • la colonne std décrit l’heure d’hiver,
  • la colonne dst l’heure saisonnière (daylight saving time) d’été (c'est-à-dire 1 heure de décalage en plus par rapport à l’heure d’hiver),
  • la colonne 2dst une seconde heure saisonnière (par exemple BDST est le British Double Summer Time utilisé en Angleterre de 1941 à 1945 et en 1947).


#              std dst  2dst
#              LMT           Local Mean Time
#  -4:00       AST ADT       Atlantic
#  -3:00       WGT WGST      Western Greenland*
#  -1:00       EGT EGST      Eastern Greenland*
#   0:00       GMT BST  BDST Greenwich, British Summer<
#   0:00       GMT IST       Greenwich, Irish Summer
#   0:00       WET WEST WEMT Western Europe
#   0:19:32.13 AMT NST       Amsterdam, Netherlands Summer (1835-1937)*
#   0:20       NET NEST      Netherlands (1937-1940)*
#   1:00       CET CEST CEMT Central Europe
#   1:00:14    SET           Swedish (1879-1899)*
#   2:00       EET EEST      Eastern Europe
#   3:00       MSK MSD       Moscow

En ce qui concerne la France, le name de l’heure d’hiver est CET (Central European Time) ; celui de l’heure d’été est CEST (Central European Summer Time).

Si on revient au fichier javascript décrivant paris, le fichier stocke un tableau global dans une variable locale zone (et comme le montre l'extrait suivant, il comporte théoriquement le timezone offset théoriquement jusqu’en 9999).


var zone = [
{
"from": -377711769600000, // -9999-01-01T00:00:00Z
"to": -2486678901000, // 1891-03-14T23:51:39Z
"dst": false,
"offset": 561,
"name": "LMT"
},


{
"from": 1269738000000, // 2010-03-28T01:00:00Z
"to": 1288486800000, // 2010-10-31T01:00:00Z
"dst": true,
"offset": 7200,
"name": "CEST"
},
{
"from": 1288486800000, // 2010-10-31T01:00:00Z
"to": 1301187600000, // 2011-03-27T01:00:00Z
"dst": false,
"offset": 3600,
"name": "CET"
},

{
"from": 2550704400000, // 2050-10-30T01:00:00Z
"to": 253402300799000, // 9999-12-31T23:59:59Z
"dst": false,
"offset": 3600,
"name": "CET"
}
] ;

En utilisant ces informations, il est donc possible de déterminer quel sera le décalage horaire (par rapport à l’UTC) d’une date quel que soit son fuseau horaire en sélectionnant la bonne période (par parcours du tableau zone et comparaison avec les propriétés from et to).

Nous verrons dans un prochain article comment mettre en oeuvre cette possibilité.

Un commentaire

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Captcha *

Ce site utilise Akismet pour réduire les indésirables. En savoir plus sur comment les données de vos commentaires sont utilisées.