web-dev-qa-db-fra.com

Meilleures pratiques pour l'heure et le fuseau horaire

J'espère faire de cette question et de ses réponses le guide ultime pour gérer l'heure d'été, en particulier pour gérer les changements effectifs.

Si vous avez quelque chose à ajouter, merci de le faire

De nombreux systèmes dépendent de la précision de l'heure. Le problème réside dans les changements d'heure dus à l'heure avancée, qui font avancer ou reculer l'horloge.

Par exemple, dans un système de prise de commande, les règles de gestion dépendent de l'heure de la commande. Si l'horloge change, les règles risquent de ne pas être aussi claires. Comment faut-il conserver l'heure de la commande? Il existe bien sûr un nombre infini de scénarios - celui-ci est simplement illustratif.

  • Comment avez-vous traité le problème de l'heure avancée?
  • Quelles hypothèses font partie de votre solution? (cherche contexte ici)

Aussi important, sinon plus:

  • Qu'as-tu essayé qui n'a pas fonctionné?
  • Pourquoi cela n'a-t-il pas fonctionné?

Je serais intéressé par la programmation, le système d'exploitation, la persistance des données et d'autres aspects pertinents de la question.

Les réponses générales sont excellentes, mais j'aimerais aussi voir les détails, surtout s'ils ne sont disponibles que sur une seule plateforme.

1992
Oded

Résumé des réponses et autres données: (veuillez ajouter les vôtres)

Faites:

  • Chaque fois que vous vous référez à un moment exact dans le temps, persistez l'heure selon une norme unifiée qui n'est pas affectée par l'heure d'été. (GMT et UTC sont équivalents à cet égard, mais il est préférable d'utiliser le terme UTC. Notez que UTC est également appelé zoulou ou Z temps.)
  • Si, au lieu de cela, vous choisissez de conserver une heure en utilisant une valeur d'heure locale, incluez le décalage de l'heure locale pour cette heure particulière à partir de l'heure UTC (ce décalage peut changer au cours de l'année), de sorte que l'horodatage puisse être interprété ultérieurement sans ambiguïté.
  • Dans certains cas, vous devrez peut-être stocker à la fois l'heure UTC et l'heure locale équivalente. Cela se fait souvent avec deux champs distincts, mais certaines plates-formes prennent en charge un type datetimeoffset pouvant stocker les deux dans un seul champ.
  • Lorsque vous stockez des horodatages sous forme de valeur numérique, utilisez le temps Unix - qui correspond au nombre de secondes entières depuis 1970-01-01T00:00:00Z (à l'exclusion des secondes intercalaires). Si vous avez besoin d'une plus grande précision, utilisez plutôt les millisecondes. Cette valeur doit toujours être basée sur UTC, sans aucun ajustement de fuseau horaire.
  • Si vous devez éventuellement modifier l'horodatage ultérieurement, incluez l'ID de fuseau horaire d'origine afin de déterminer si le décalage peut avoir changé par rapport à la valeur d'origine enregistrée.
  • Lors de la planification d'événements futurs, l'heure locale est généralement préférée à l'heure UTC, car il est courant que le décalage change. Voir les réponses et article de blog .
  • Lorsque vous stockez des dates entières, telles que les anniversaires et les anniversaires, ne convertissez pas en UTC ni en aucun autre fuseau horaire.
    • Lorsque cela est possible, stockez-le dans un type de données avec une date uniquement qui n'inclut pas l'heure.
    • Si un tel type n'est pas disponible, veillez à toujours ignorer l'heure du jour lors de l'interprétation de la valeur. Si vous ne pouvez pas être sûr que l'heure du jour sera ignorée, choisissez 12 h 00 plutôt que 00 h 00 comme heure représentative plus sûre pour cette journée.
  • N'oubliez pas que les décalages de fuseaux horaires ne représentent pas toujours un nombre entier d'heures (par exemple, l'heure standard indienne est l'heure UTC + 05: 30 et le Népal utilise l'heure UTC + 05: 45).
  • Si vous utilisez Java, utilisez Java.time pour Java 8 et versions ultérieures.
  • Si vous utilisez . NET , envisagez d’utiliser Noda Time .
  • Si vous utilisez .NET sans Noda Time, considérez que DateTimeOffset est souvent un meilleur choix que DateTime.
  • Si vous utilisez Perl, utilisez DateTime .
  • Si vous utilisez Python, utilisez pytz ou dateutil .
  • Si vous utilisez JavaScript, utilisez moment.js avec l’extension moment-timezone .
  • Si vous utilisez PHP> 5.2, utilisez les conversions de fuseaux horaires natifs fournies par les classes DateTime et DateTimeZone. Soyez prudent lorsque vous utilisez DateTimeZone::listAbbreviations() - voir réponse . Pour conserver PHP avec les données Olson à jour, installez périodiquement le paquet PECL timezonedb ; voir la réponse .
  • Si vous utilisez C++, veillez à utiliser une bibliothèque utilisant correctement la base de données de fuseau horaire IANA . Celles-ci comprennent cctz , ICU et la bibliothèque "tz" de Howard Hinnant .
    • N'utilisez pas Boost pour les conversions de fuseaux horaires. Alors que son API prétend prendre en charge les identifiants IANA standard (ou "zoneinfo"), elle les mappe grossièrement avec des données de style POSIX, sans tenir compte des éléments riches. historique des changements que chaque zone a pu avoir. (En outre, le fichier n'est plus en maintenance.)
  • Si vous utilisez Rust, utilisez chrono .
  • La plupart des règles commerciales utilisent le temps civil, plutôt que UTC ou GMT. Par conséquent, prévoyez de convertir les horodatages UTC en un fuseau horaire local avant d'appliquer la logique d'application.
  • Rappelez-vous que les fuseaux horaires et les décalages ne sont pas fixes et peuvent changer. Par exemple, historiquement, les États-Unis et le Royaume-Uni ont utilisé les mêmes dates pour "avancer" et "se replier". Cependant, en 2007, les États-Unis ont modifié les dates auxquelles les horloges sont modifiées. Cela signifie maintenant que pour 48 semaines de l'année, la différence entre l'heure de Londres et l'heure de New York est de 5 heures et pour 4 semaines (3 au printemps et 1 à l'automne), de 4 heures. Tenez compte des éléments de ce type dans tous les calculs impliquant plusieurs zones.
  • Considérez le type d’heure (heure réelle de l’événement, heure de diffusion, heure relative, heure historique, heure récurrente), quels éléments (horodatage, décalage de fuseau horaire et nom de fuseau horaire) que vous devez enregistrer pour une récupération correcte - voir "Types d’heure" dans cette réponse .
  • Gardez synchronisés vos fichiers tzdata de système d’exploitation, de base de données et d’applications, entre eux et le reste du monde.
  • Sur les serveurs, définissez les horloges matérielles et OS sur UTC plutôt que sur un fuseau horaire local.
  • Quel que soit le point précédent, le code côté serveur, sites Web compris, ne doit jamais attendre le fuseau horaire local du serveur. être quelque chose en particulier. voir la réponse .
  • Préférez travailler avec les fuseaux horaires au cas par cas dans le code de votre application plutôt que globalement via les paramètres de fichier de configuration ou les paramètres par défaut.
  • Utilisez NTP des services sur tous les serveurs.
  • Si vous utilisez FAT32 , n'oubliez pas que les horodatages sont stockés à l'heure locale, et non à l'heure UTC.
  • Lorsqu’il s’agit d’événements récurrents (émission télévisée hebdomadaire, par exemple), n’oubliez pas que l’heure change avec DST et sera différente d’un fuseau horaire à l’autre.
  • Interrogez toujours les valeurs date-heure en tant que , borne inférieure incluse, borne supérieure exclusive (>=, <).

Ne pas:

  • Ne confondez pas un "fuseau horaire", tel que America/New_York avec un "décalage de fuseau horaire", tel que -05:00. Ce sont deux choses différentes. Voir le wiki de la balise de fuseau horaire .
  • N'utilisez pas l'objet Date de JavaScript pour effectuer des calculs de date et d'heure dans les navigateurs Web plus anciens, car ECMAScript version 5.1 ou antérieure présente un défaut de conception qui peut utiliser de manière incorrecte l'heure d'été. (Ceci a été corrigé dans ECMAScript 6/2015).
  • Ne faites jamais confiance à l'horloge du client. Cela peut très bien être incorrect.
  • Ne dites pas aux gens de "toujours utiliser l'UTC partout". Cet avis répandu repose sur plusieurs scénarios valables, décrits plus haut dans ce document. Utilisez plutôt la référence de temps appropriée pour les données avec lesquelles vous travaillez. ( L'horodatage peut utiliser le temps universel coordonné, mais les futures dates de planification et les dates uniquement ne le devraient pas.)

Test:

  • Lors des tests, assurez-vous de tester les pays des hémisphères occidentaux, orientaux, nordiques et (en fait, dans chaque quart du monde, soit quatre régions), avec les deux DST en cours et non (donne 8), et un pays qui n'utilise pas l'heure d'été (4 autres pays pour couvrir toutes les régions, soit 12 au total).
  • Testez la transition de l'heure d'été, c.-à-d. Lorsque vous êtes actuellement en heure d'été, sélectionnez une valeur d'heure en hiver.
  • Testez les scénarios de limite, tels qu'un fuseau horaire UTC + 12 avec DST, établissant l'heure locale UTC + 13 en été et même des lieux au format UTC + 13 en hiver
  • Testez toutes les bibliothèques et applications tierces et assurez-vous qu'elles gèrent correctement les données de fuseau horaire.
  • Testez les fuseaux horaires d’une demi-heure au moins.

Référence:

Autre:

  • Faites pression sur votre représentant pour qu'il mette fin à l'abomination qu'est l'heure d'été. On peut toujours espérer ...
  • Lobby pour l'heure normale de la Terre
883
Yuval Adam

Je ne sais pas ce que je peux ajouter aux réponses ci-dessus, mais voici quelques points de ma part:

Types de temps

Vous devez considérer quatre moments différents:

  1. Heure de l'événement: par exemple, l'heure à laquelle se produit un événement sportif international ou un couronnement/décès/etc. Cela dépend du fuseau horaire de l'événement et non du spectateur.
  2. Heure de télévision: par exemple, une émission de télévision donnée est diffusée à 21 heures, heure locale, dans le monde entier. Important pour penser à publier les résultats (par exemple, American Idol) sur votre site Web
  3. Temps relatif: Exemple: Cette question a une prime ouverte qui se ferme dans 21 heures. C'est facile à afficher
  4. Heure récurrente: Exemple: une émission télévisée est diffusée tous les lundis à 21 heures, même en cas de modification de l'heure d'été.

Il y a aussi historique/temps alternatif. Ce sont agaçants car ils peuvent ne pas correspondre à l'heure normale. Ex: dates juliennes, dates selon un calendrier lunaire de Saturne, le calendrier Klingon.

L'enregistrement des horodatages de début/fin en UTC fonctionne bien. Pour 1, vous avez besoin d'un nom de fuseau horaire d'événement + offset stocké avec l'événement. Pour 2, vous avez besoin d’un identifiant d’heure locale stocké avec chaque région et d’un nom de fuseau horaire local + décalage stockés pour chaque visualiseur (il est possible de le déduire de l’IP si vous êtes en crise). Pour 3, enregistrez en secondes UTC et n’avez pas besoin de fuseaux horaires. 4 est un cas particulier de 1 ou 2 selon qu'il s'agisse d'un événement global ou local, mais vous devez également stocker un créé à horodatage afin que vous peut indiquer si une définition de fuseau horaire a été modifiée avant ou après la création de cet événement. Cela est nécessaire si vous devez afficher des données historiques.

Temps de stockage

  • Toujours stocker l'heure en UTC
  • Convertir en heure locale affichée (heure locale définie par l'utilisateur qui regarde les données)
  • Lorsque vous enregistrez un fuseau horaire, vous avez besoin du nom, de l'horodatage et du décalage. Cela est nécessaire car les gouvernements changent parfois la signification de leur fuseau horaire (par exemple: le gouvernement américain a modifié les dates de l'heure d'été), et votre application doit gérer les choses avec élégance ... modifié.

Décalages et noms

Un exemple de ce qui précède serait:

La finale de la coupe du monde de football a eu lieu en Afrique du Sud (UTC + 2 - SAST) le 11 juillet 2010 à 19h00 UTC.

Avec ces informations, nous pouvons déterminer historiquement l’heure exacte à laquelle la finale du WCS a eu lieu même si la définition du fuseau horaire sud-africaine change et peut être affichée aux téléspectateurs dans leur région. fuseau horaire au moment où ils interrogent la base de données.

Le temps du système

Vous devez également synchroniser les fichiers tzdata de votre système d'exploitation, de votre base de données et de votre application, à la fois entre eux et avec le reste du monde, et effectuer des tests approfondis lors de la mise à niveau. Il n'est pas rare qu'une application tierce dont vous dépendez n'ait pas géré correctement un changement de zone de stockage.

Assurez-vous que les horloges matérielles sont définies sur UTC et, si vous utilisez des serveurs dans le monde entier, assurez-vous que leurs systèmes d'exploitation sont également configurés pour utiliser l'UTC. Cela devient évident lorsque vous devez copier des fichiers journaux Apache soumis à une rotation horaire à partir de serveurs dans plusieurs fuseaux horaires. Les trier par nom de fichier ne fonctionne que si tous les fichiers sont nommés avec le même fuseau horaire. Cela signifie également que vous n'êtes pas obligé de faire des calculs mathématiques dans votre tête lorsque vous passez d'une boîte à une autre et que vous devez comparer les horodatages.

En outre, exécutez ntpd sur toutes les boîtes.

Les clients

Ne faites jamais confiance à l'horodatage que vous obtenez d'un ordinateur client comme étant valide. Par exemple, les en-têtes Date: HTTP ou un appel javascript Date.getTime(). Celles-ci conviennent très bien lorsqu'elles sont utilisées comme identificateurs opaques ou lorsque vous faites des calculs mathématiques au cours d'une seule session sur le même client, mais n'essayez pas de faire une référence croisée à ces valeurs avec quelque chose que vous avez sur le serveur. Vos clients n'exécutent pas NTP et ne disposent pas nécessairement d'une batterie en état de fonctionnement pour leur horloge BIOS.

Trivia

Enfin, les gouvernements font parfois des choses très étranges:

Aux Pays-Bas, l'heure normale était exactement de 19 minutes et 32,13 secondes d'avance sur UTC, conformément à la loi, du 1909-05-01 au 1937-06-30. Ce fuseau horaire ne peut pas être représenté exactement en utilisant le format HH: MM.

Ok, je pense que j'ai fini.

307
bluesmoon

C'est un problème important et étonnamment difficile. La vérité est qu’il n’existe pas de norme totalement satisfaisante pour la persistance du temps. Par exemple, le standard SQL et le format ISO (ISO 8601) ne sont clairement pas suffisants.

Du point de vue conceptuel, on traite généralement deux types de données de date/heure et il convient de les distinguer (les normes ci-dessus ne le font pas): " le temps physique "et" heure civile ".

Un instant de temps "physique" est un point de la chronologie universelle continue à laquelle la physique traite (en ignorant la relativité, bien sûr). Ce concept peut être codé de manière adéquate et persister en UTC, par exemple (si vous pouvez ignorer les secondes intercalaires).

Une "heure civile" est une spécification de date/heure qui suit les normes civiles: un instant ici est entièrement spécifié par un ensemble de champs de date/heure (Y, M, J, H, MM, S, FS) plus une TZ (spécification de fuseau horaire) (également un "calendrier", en fait; mais supposons que nous limitions la discussion au calendrier grégorien). Un fuseau horaire et un calendrier permettent conjointement (en principe) de mapper d'une représentation à une autre. Mais les instants de temps civils et physiques sont fondamentalement des types de grandeurs différents, et ils doivent être séparés conceptuellement et traités différemment (une analogie: tableaux d’octets et chaînes de caractères).

La question est confuse parce que nous parlons de ces types d’événements de manière interchangeable et que les temps civils sont sujets à des changements politiques. Le problème (et la nécessité de distinguer ces concepts) devient plus évident pour les événements à venir. Exemple (tiré de ma discussion ici .

John enregistre dans son calendrier un rappel d’événement à la date et à l’heure 2019-Jul-27, 10:30:00, TZ = Chile/Santiago, (avec décalage GMT-4 et correspond donc à UTC 2019-Jul-27 14:30:00). Mais un jour dans l’avenir, le pays décide de changer l’offset TZ en GMT-5.

Maintenant, quand le jour vient ... si ce rappel se déclenche à

A) 2019-Jul-27 10:30:00 Chile/Santiago = UTC time 2019-Jul-27 15:30:00?

ou

B) 2019-Jul-27 9:30:00 Chile/Santiago = UTC time 2019-Jul-27 14:30:00?

Il n’ya pas de réponse correcte, à moins que l’on sache ce que John pensait conceptuellement en disant au calendrier "Appelle-moi, appelle-moi à 2019-Jul-27, 10:30:00 TZ=Chile/Santiago".

Voulait-il dire un "jour civil" ("quand les horloges de ma ville disent 10h30")? Dans ce cas, A) est la bonne réponse.

Ou voulait-il dire un "instant physique du temps", un point dans la ligne continue du temps de notre univers, par exemple, "quand la prochaine éclipse solaire aura lieu". Dans ce cas, la réponse B) est la bonne.

Quelques API Date/Heure ont cette distinction: Jodatime , qui constitue le fondement de la prochaine (troisième!) Java API DateTime (JSR 310).

86
leonbloy

Séparez clairement les préoccupations architecturales - pour savoir exactement quel niveau interagit avec les utilisateurs et doit changer la date/heure pour/à partir de la représentation canonique (UTC). La date et l'heure en dehors de l'heure UTC correspondent à la présentation (suit le fuseau horaire local de l'utilisateur), l'heure UTC est le modèle (reste unique pour les niveaux dorsal et intermédiaire).

En outre, décidez quel est votre public actuel, ce que vous n'avez pas à servir et où tracez-vous la ligne. Ne touchez pas à des calendriers exotiques, sauf si vous y avez des clients importants, puis envisagez de créer un ou plusieurs serveurs distincts pour chaque région, uniquement pour cette région.

Si vous pouvez acquérir et conserver l'emplacement de l'utilisateur, utilisez cet emplacement pour la conversion systématique date-heure (par exemple, une culture .NET ou une table SQL), mais fournissez un moyen pour l'utilisateur final de choisir des remplacements si la date-heure est essentielle pour vos utilisateurs.

S'il y a des obligations de vérification historiques impliqué (comme dire exactement quand Jo en AZ a payé une facture il y a 2 ans en septembre) alors conservez l'heure UTC et l'heure locale pour l'enregistrement (votre les tables de conversion changeront avec le temps).

Définissez le fuseau horaire de référence pour les données en vrac - comme des fichiers, des services Web, etc. Dites qu'une entreprise de la côte Est dispose d'un centre de données en CA. Vous devez demander et savoir ce qu'ils utilisent comme norme. d'assumer l'un ou l'autre.

Ne vous fiez pas aux décalages de fuseaux horaires intégrés dans la représentation textuelle de la date et de l'heure et n'accepte pas de les analyser et de les suivre. Au lieu de cela, demandez toujours que le fuseau horaire et/ou la zone de référence soient explicitement définis. Vous pouvez facilement recevoir l'heure avec un décalage PST, mais l'heure est en fait EST, car il s'agit de l'heure de référence du client et les enregistrements ont simplement été exportés sur un serveur qui se trouve dans PST.

56
ZXX

Vous devez connaître la base de données Olson tz database , disponible à ftp://elsie.nci.nih.gov/pub http://iana.org/time-zones/ . Il est mis à jour plusieurs fois par an pour tenir compte des changements souvent de dernière minute intervenant dans le choix du moment (et de l'heure à laquelle) pour passer de l'heure d'hiver à l'heure d'été (heure d'été ou d'hiver) dans différents pays du monde. En 2009, la dernière version était celle de 2009; en 2010, c'était 2010n; en 2011, c'était 2011n; à la fin du mois de mai 2012, la publication était 2012c. Notez qu'il existe un ensemble de code permettant de gérer les données et les données de fuseau horaire proprement dites, dans deux archives distinctes (tzcode20xxy.tar.gz et tzdata20xxy.tar.gz). Le code et les données sont dans le domaine public.

Il s'agit de la source de noms de fuseaux horaires tels que America/Los_Angeles (et de synonymes tels que US/Pacific).

Si vous devez suivre différentes zones, vous avez besoin de la base de données Olson. Comme d'autres l'ont conseillé, vous souhaitez également stocker les données dans un format fixe (UTC est normalement celui choisi), ainsi qu'un enregistrement du fuseau horaire dans lequel les données ont été générées. Vous souhaiterez peut-être faire la distinction entre le décalage par rapport à UTC à l'heure et le nom du fuseau horaire; cela peut faire la différence plus tard. De plus, savoir qu’il s’agit actuellement de 2010-03-28T23: 47: 00-07: 00 (États-Unis/Pacifique) peut vous aider ou non à interpréter la valeur 2010-11-15T12: 30 - qui est probablement spécifiée dans PST ( Heure normale du Pacifique) au lieu de l’heure avancée du Pacifique.

Les interfaces de bibliothèque C standard ne sont pas terriblement utiles avec ce genre de choses.


Les données Olson ont été déplacées, en partie parce que DA D Olson va bientôt prendre sa retraite, et en partie parce qu’un procès (maintenant rejeté) a été intenté contre les responsables de la maintenance pour violation du droit d’auteur. La base de données de fuseaux horaires est maintenant gérée sous les auspices de IANA , l'autorité Internet de numéros attribués, et la page d'accueil contient un lien vers "Base de données de fuseaux horaires" . La liste de discussion est maintenant [email protected]; la liste des annonces est [email protected].

39
Jonathan Leffler

En général, inclut le décalage de l'heure locale (y compris le décalage de l'heure d'été) dans les horodatages stockés: l'heure UTC seule ne suffit pas si vous souhaitez afficher ultérieurement l'horodatage dans son format. fuseau horaire d'origine (et réglage de l'heure d'été).

N'oubliez pas que le décalage n'est pas toujours un nombre entier d'heures (par exemple, l'heure standard indienne est UTC + 05: 30).

Par exemple, les formats appropriés sont un Tuple (heure unix, décalage en minutes) ou ISO 8601 .

25
oefe

Traverser la frontière du "temps informatique" et du "temps humain" est un cauchemar. Le principal est qu’il n’existe aucune sorte de norme pour les règles régissant les fuseaux horaires et l’heure avancée. Les pays sont libres de modifier leurs règles de fuseau horaire et d'heure d'été à tout moment, et ils le font.

Certains pays, par exemple Israël et le Brésil décident chaque année de l'heure avancée, il est donc impossible de savoir à l'avance quand (si) l'heure d'été sera effective. D'autres ont fixé (ish) des règles quant à quand DST est en vigueur. D'autres pays n'utilisent pas l'heure d'été comme tous.

Les fuseaux horaires ne doivent pas nécessairement être des différences d'heure complète par rapport à l'heure GMT. Le Népal est +5.45. Il y a même des fuseaux horaires qui sont +13. Cela signifie que:

Sun 23:00 in Howland Island (-12)
MON 11:00 GMT 
TUE 00:00 in Tonga (+13)

sont tous la même heure, pourtant 3 jours différents!

Il n’existe pas non plus de norme claire sur les abréviations des fuseaux horaires et sur la façon dont elles changent à l’heure d'été, vous vous retrouvez ainsi:

AST Arab Standard Time     UTC+03
AST Arabian Standard Time  UTC+04
AST Arabic Standard Time   UTC+03

Le meilleur conseil est d'éviter autant que possible les heures locales et de rester à l'UTC autant que possible. Convertissez uniquement aux heures locales au dernier moment possible.

Lors du test, assurez-vous de tester les pays des hémisphères occidentaux et orientaux, avec ou sans le DST en cours et avec un pays qui ne l'utilise pas (6 au total).

23
Richard

Pour PHP:

La classe DateTimeZone dans PHP> 5.2 est déjà basée sur la base de données Olson mentionnée par d’autres. Par conséquent, si vous effectuez des conversions de fuseau horaire dans PHP et non dans la base de données, vous êtes dispensé de travailler. avec les fichiers Olson (difficiles à comprendre).

Cependant, PHP n'est pas mis à jour aussi souvent que la base de données Olson. Par conséquent, le simple fait d'utiliser les conversions de fuseau horaire PHP peut vous laisser avec des informations DST obsolètes et influer sur l'exactitude de vos données. Bien que cela ne devrait pas se produire fréquemment, cela peut arriver, et se produira si vous avez un grand nombre d'utilisateurs dans le monde entier.

Pour faire face au problème ci-dessus, utilisez le paquetage timezonedb pecl , sa fonction consiste à mettre à jour les données de fuseau horaire de PHP. Installez ce paquet aussi souvent qu'il est mis à jour. (Je ne sais pas si les mises à jour de ces paquets suivent exactement les mises à jour Olson, mais il semble que la fréquence de mise à jour soit très proche de celle des mises à jour Olson.)

20
shealtiel

Si votre conception le permet, évitez la conversion de l'heure locale en même temps!

Cela peut sembler insensé à certains, mais pensez à UX: les utilisateurs traitent les dates proches (aujourd'hui, hier, lundi prochain) plus rapidement que les dates absolues (vendredi 09 septembre 2010 - 17.17). Et quand vous y réfléchissez davantage, la précision des fuseaux horaires (et de l'heure d'été) est d'autant plus importante que la date est proche de now(), donc si vous pouvez exprimer des dates/dates-heures dans un format relatif de +/- 1 ou 2 semaines, le reste des dates peut être UTC et cela importera peu à 95% des utilisateurs.

De cette façon, vous pouvez stocker toutes les dates au format UTC, effectuer les comparaisons relatives au format UTC et simplement afficher les dates UTC de l'utilisateur en dehors de votre seuil de date relative.

Cela peut également s'appliquer à la saisie de l'utilisateur (mais généralement de manière plus limitée). La sélection dans un menu déroulant comportant uniquement {Hier, aujourd'hui, demain, lundi prochain, jeudi prochain} est tellement plus simple et plus facile pour l'utilisateur qu'un sélecteur de date. Les sélecteurs de dattes sont parmi les composants les plus douloureux du remplissage des formulaires. Bien sûr, cela ne fonctionnera pas dans tous les cas, mais vous pouvez constater qu’il suffit d’un peu de design astucieux pour le rendre très puissant.

17
Matt Kocaj

Bien que je ne l'aie pas essayée, une approche des ajustements de fuseau horaire qui me conviendrait le mieux serait la suivante:

  1. Tout stocker en UTC.

  2. Créez une table TZOffsets avec trois colonnes: RegionClassId, StartDateTime et OffsetMinutes (int, en minutes).

Dans la table, stockez une liste de dates et d'heures lorsque l'heure locale a changé et de combien. Le nombre de régions dans le tableau et le nombre de dates dépendent de la plage de dates et de régions du monde à prendre en charge. Pensez-y comme si c'était une date "historique", même si les dates devraient inclure l'avenir à une certaine limite pratique.

Lorsque vous devez calculer l'heure locale d'une heure UTC, procédez comme suit:

SELECT DATEADD('m', SUM(OffsetMinutes), @inputdatetime) AS LocalDateTime
FROM   TZOffsets
WHERE  StartDateTime <= @inputdatetime
       AND RegionClassId = @RegionClassId;

Vous voudrez peut-être mettre en cache cette table dans votre application et utiliser LINQ ou un moyen similaire pour effectuer les requêtes plutôt que de consulter la base de données.

Ces données peuvent être extraites de base de données tz du domaine public .

Avantages et notes de bas de page de cette approche:

  1. Aucune règle n'est intégrée au code, vous pouvez facilement ajuster les décalages pour les nouvelles régions ou les plages de dates.
  2. Vous n'êtes pas obligé de prendre en charge toutes les plages de dates ou régions, vous pouvez les ajouter si nécessaire.
  3. Les régions ne doivent pas nécessairement correspondre directement aux limites géopolitiques et pour éviter la duplication de lignes (par exemple, la plupart des États américains gèrent l’heure d’été de la même manière), vous pouvez avoir de larges entrées RegionClass qui se lient dans un autre tableau à des listes plus traditionnelles. états, pays, etc.
  4. Pour des situations comme les États-Unis, où les dates de début et de fin de l'heure d'été ont changé au cours des dernières années, c'est assez facile à gérer.
  5. Etant donné que le champ StartDateTime peut également stocker une heure, l’heure de basculement standard à 2h00 est facilement gérée.
  6. Pas partout dans le monde utilise une heure avancée d'été. Cela gère ces cas facilement.
  7. La table de données est multi-plateforme et pourrait être un projet open source distinct pouvant être utilisé par les développeurs qui utilisent presque toutes les plateformes de base de données ou tous les langages de programmation.
  8. Cela peut être utilisé pour les décalages qui n'ont rien à voir avec les fuseaux horaires. Par exemple, les ajustements d'une seconde qui se produisent de temps en temps pour ajuster la rotation de la Terre, les ajustements historiques au calendrier grégorien, etc.
  9. Comme il s'agit d'une table de base de données, les requêtes de rapport standard, etc. peuvent exploiter les données sans passer par le code de la logique applicative.
  10. Cela gère également les décalages de fuseaux horaires si vous le souhaitez, et peut même prendre en compte des cas historiques particuliers dans lesquels une région est affectée à un autre fuseau horaire. Tout ce dont vous avez besoin est une date initiale qui attribue un décalage de fuseau horaire à chaque région avec une date de début minimale. Cela nécessiterait de créer au moins une région pour chaque fuseau horaire, mais vous permettrait de poser des questions intéressantes telles que: "Quelle est la différence en heure locale entre Yuma, Arizona et Seattle, Washington le 2 février 1989 à 5 heures du matin?" (Soustrayez simplement un SUM () de l'autre).

Maintenant, le seul inconvénient de cette approche ou de toute autre est que les conversions de l’heure locale à l’heure GMT ne sont pas parfaites, car tout changement DST qui a un décalage négatif par rapport à l’horloge répète une heure locale donnée. Je crains que ce ne soit pas un moyen facile de régler ce problème. C’est une des raisons pour lesquelles enregistrer l’heure locale est une mauvaise nouvelle en premier lieu.

15
richardtallent

Je me suis penché sur deux types de systèmes, les "systèmes de planification des équipes (par exemple, les ouvriers d’usine)" et les "systèmes de gestion dépendants du gaz)…

Les journées de 23 et 25 heures sont pénibles, de même que les quarts de travail de 8 heures qui durent entre 7 et 9 heures. Le problème est que vous constaterez que chaque client, ou même chaque service du client, a créé des règles différentes (souvent sans documenter) sur ce qu’il fait dans ces cas particuliers.

Il est préférable de ne pas poser certaines questions au client avant que celui-ci ait payé votre logiciel "standard". Il est très rare de trouver un client qui réfléchisse à ce type de problème dès l’achat de logiciel.

Je pense que dans tous les cas, vous devriez enregistrer l'heure au format UTC et convertir en/à partir de l'heure locale avant d'enregistrer la date et l'heure. Cependant, même savoir quelle heure est prise peut être difficile avec l'heure d'été et les fuseaux horaires.

14
Ian Ringrose

J'ai récemment eu un problème dans une application Web où, après Ajax, la date-heure renvoyée sur mon code côté serveur était différente de la date et l'heure servies.

Cela concernait très probablement mon code JavaScript sur le client qui a construit la date de publication sur le client sous forme de chaîne, car JavaScript s'ajuste en fonction du fuseau horaire et de l'heure avancée, et dans certains navigateurs, le calcul du moment auquel appliquer l'heure avancée. semblait être différent de celui des autres.

En fin de compte, j'ai choisi de supprimer entièrement les calculs de date et d'heure sur le client et de l'envoyer à mon serveur sur une clé entière qui a ensuite été traduite en heure de jour sur le serveur, afin de permettre des transformations cohérentes.

Ce que je retiens de ceci: N'utilisez pas les calculs de date et heure JavaScript dans les applications Web à moins que vous ne deviez ABSOLUMENT le faire.

13
Joon

Lorsqu'il s'agit d'applications qui s'exécutent sur un serveur, y compris les sites Web et autres services principaux, le paramètre de fuseau horaire du serveur doit être ignoré par l'application.

Le conseil commun est de définir le fuseau horaire du serveur sur UTC. Il s’agit bien d’une bonne pratique, mais c’est là une aide précieuse pour les applications qui ne suivent pas d’autres meilleures pratiques. Par exemple, un service peut écrire dans des fichiers journaux avec des horodatages locaux au lieu d'horodatages basés sur UTC, créant ainsi des ambiguïtés lors de la transition de repli de l'heure d'été. La définition du fuseau horaire du serveur sur UTC corrigera l'application that. Cependant, le vrai remède serait que l’application se connecte en commençant par UTC.

Le code côté serveur, y compris les sites Web, doit jamais s'attendre à ce que le fuseau horaire local du serveur soit particulier.

Dans certaines langues, le fuseau horaire local peut facilement s’insérer dans le code de l’application. Par exemple, la méthode DateTime.ToUniversalTime dans .NET convertit from le fuseau horaire local en UTC, et la propriété DateTime.Now renvoie l'heure actuelle dans le fuseau horaire local. De plus, le constructeur Date en JavaScript utilise le fuseau horaire local de l'ordinateur. Il y a beaucoup d'autres exemples comme celui-ci. Il est important de pratiquer la programmation défensive en évitant tout code utilisant le paramètre de fuseau horaire local de l'ordinateur.

Réservez en utilisant le fuseau horaire local pour le code côté client, tel que les applications de bureau, les applications mobiles et le JavaScript côté client.

12
Matt Johnson-Pint

Pour le Web, les règles ne sont pas si compliquées ...

  • Côté serveur, utilisez l'UTC
  • Côté client, utilisez Olson
    • Raison: les décalages UTC ne sont pas sûrs de l'heure d'été (par exemple, New York est HNE (UTC - 5 heures) une partie de l'année, EDT (UTC - 4 heures) le reste de l'année).
    • Pour la détermination du fuseau horaire côté client, vous avez deux options:
      • 1) Définir la zone définie par l'utilisateur (Safer)
      • 2) Détecter automatiquement la zone

Le reste ne concerne que la conversion UTC/locale à l'aide de vos bibliothèques datetime côté serveur. Bon aller ...

11
Yarin

Laissez vos serveurs réglés sur UTC et assurez-vous qu’ils sont tous configurés pour NTP ou l’équivalent.

UTC évite les problèmes liés à l'heure d'été et les serveurs désynchronisés peuvent entraîner des résultats imprévisibles nécessitant un certain temps pour effectuer un diagnostic.

10
Andrew B

Soyez prudent lorsque vous traitez avec des horodatages stockés dans le système de fichiers FAT32 - il est toujours conservé dans les coordonnées temporelles locales (qui incluent DST - voir article msdn ). Je me suis brûlé dessus.

9
paquetp

Une autre chose, assurez-vous que le correctif de l'heure d'été à jour est appliqué sur les serveurs.

L'année dernière, nous avons connu une situation où notre temps était constamment inférieur d'une heure pendant trois semaines aux utilisateurs nord-américains, même si nous utilisions un système basé sur UTC.

En fin de compte, c’était les serveurs. Ils avaient juste besoin d'un correctif à jour appliqué ( Windows Server 20 ).

7
Solyad

PHP DateTimeZone::listAbbreviations() output

Cette méthode PHP renvoie un tableau associatif contenant des fuseaux horaires "majeurs" (comme CEST), qui contiennent à leur tour des fuseaux horaires "géographiques" plus spécifiques (tels que Europe/Amsterdam).

Si vous utilisez ces fuseaux horaires et leurs informations de décalage/DST, il est extrêmement important de réaliser ce qui suit:

Il semble que toutes les configurations offset/DST différentes (y compris les configurations historiques) de chaque fuseau horaire soient incluses!

Par exemple, Europe/Amsterdam peut être trouvé six fois dans la sortie de cette fonction. Deux occurrences (offset 1172/4772) correspondent à l’heure d’Amsterdam jusqu’en 1937; deux (1200/4800) correspondent à la période utilisée entre 1937 et 1940; et deux (3600/4800) sont utilisés depuis 1940.

Par conséquent, , vous ne pouvez pas vous fier aux informations de décalage/DST renvoyées par cette fonction comme correctes/en cours d'utilisation!

Si vous voulez connaître le décalage/l'heure d'été d'un certain fuseau horaire, vous devrez procéder comme suit:

<?php
$now = new DateTime(null, new DateTimeZone('Europe/Amsterdam'));
echo $now->getOffset();
?>
6
Jonathan

Si vous maintenez des systèmes de base de données qui fonctionnent avec DST actif, vérifiez avec soin s'ils doivent être arrêtés pendant la transition en automne. Mandy DBS (ou d’autres systèmes) n’aime pas passer deux fois au même endroit (local), c’est exactement ce qui se passe lorsque vous remontez l’horloge à l’automne. SAP a résolu ce problème avec une solution de contournement (à mon humble avis): au lieu de revenir en arrière, ils laissent simplement l'horloge interne fonctionner à la moitié de la vitesse habituelle pendant deux heures ...

5
vwegert

Les règles métier doivent toujours fonctionner sur heure civile (à moins qu'une législation n'indique le contraire). Sachez que le temps civil est un gâchis, mais c'est ce que les gens utilisent, alors c'est ce qui est important.

En interne, conservez les horodatages dans quelque chose comme civil-seconde-de-Epoch. Le Epoch n'a pas d'importance (je préfère le nix Epoch ) mais cela rend les choses plus faciles que l'alternative. Imaginez que secondes intercalaires n'existent pas sauf si vous faites quelque chose qui en a vraiment besoin (par exemple, le suivi par satellite) . Le mappage entre les horodatages et l'heure affichée est le seul point d'application des règles DST ; les règles changent fréquemment (au niveau mondial, plusieurs fois par an; blâmez les politiciens), vous devez donc vous assurer de ne pas coder en dur la cartographie. Olson's base de données TZ est inestimable.

5
Donal Fellows

Utilisez-vous le framework .NET ? Si tel est le cas, laissez-moi vous présenter le type DateTimeOffset , ajouté avec .NET 3.5.

Cette structure contient à la fois une DateTime et un décalage (TimeSpan), qui spécifient la différence entre la date et l'heure de l'instance DateTimeOffset et le temps universel coordonné (UTC).

  • La méthode statique DateTimeOffset.Now renvoie une instance DateTimeOffset composée de l'heure actuelle (locale) et du décalage local (comme défini dans les informations régionales du système d'exploitation).

  • La méthode statique DateTimeOffset.UtcNow retournera une instance DateTimeOffset composée de l'heure actuelle en UTC (comme si vous étiez à Greenwich).

Les autres types utiles sont les classes TimeZone et TimeZoneInfo .

4
M.A. Hanin

Pour ceux qui luttent avec cela sur . NET , voyez si utiliser DateTimeOffset et/ou TimeZoneInfo vaut la peine.

Si vous voulez utiliser fuseaux horaires IANA/Olson , ou trouvez que les types prédéfinis ne suffisent pas à vos besoins, consultez Noda Time , qui offre une date et une heure beaucoup plus intelligentes. API pour .NET.

4
Matt Johnson-Pint

Voici mon expérience: -

(Ne nécessite aucune bibliothèque tierce)

  • Sur le serveur, stockez les heures au format UTC afin que toutes les valeurs de date/heure de la base de données soient dans une seule norme, quel que soit l'emplacement des utilisateurs, des serveurs, des fuseaux horaires ou de l'heure d'été.
  • Sur la couche d'interface utilisateur ou dans les courriers électroniques envoyés à l'utilisateur, vous devez afficher les heures en fonction de l'utilisateur. Pour ce faire, vous devez avoir un décalage du fuseau horaire de l'utilisateur afin de pouvoir l'ajouter à la valeur UTC de votre base de données, ce qui donnera l'heure locale de l'utilisateur. Vous pouvez soit prendre le décalage du fuseau horaire de l'utilisateur lors de son inscription, soit le détecter automatiquement sur les plateformes Web et mobiles. Pour les sites Web, la méthode getTimezoneOffset () de JavaScript est une norme depuis la version 1.0 et est compatible avec tous les navigateurs. (Réf.: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp )
2
Doc

Je voulais juste souligner deux choses qui semblent inexactes ou du moins déroutantes:

Conservez toujours l'heure conformément à une norme unifiée qui ne soit pas affectée par l'heure d'été. GMT et UTC ont été mentionnés par différentes personnes, même si UTC semble être mentionné le plus souvent.

Aux fins de (presque) toutes les fins de calcul, UTC est en fait GMT. À moins que vous ne voyiez un horodatage avec une fraction de seconde, vous avez affaire à GMT, ce qui rend cette distinction redondante.

Incluez le décalage de l'heure locale tel quel (y compris le décalage de l'heure d'été) lors de l'enregistrement des horodatages.

Un horodatage est toujours représenté dans l'heure GMT et n'a donc pas de décalage.

2
Alix Axel

Tom Scott's vidéo sur les fuseaux horaires sur YouTube sur la chaîne Computerphile propose également une description agréable et divertissante du sujet. Les exemples comprennent:

  • Samoa (une île de l'océan Pacifique) décalant son fuseau horaire de 24 heures pour faciliter les échanges commerciaux avec l'Australie et la Nouvelle-Zélande,
  • Cisjordanie , où 2 populations de personnes suivent des fuseaux horaires différents,
  • Le 18ème siècle passe du calendrier julien au calendrier grégorien (qui s'est passé au 20ème siècle en Russie).
2
Attila Tanyi

Ne comptez jamais uniquement sur des constructeurs tels que

 new DateTime(int year, int month, int day, int hour, int minute, TimeZone timezone)

Ils peuvent déclencher des exceptions lorsqu'aucune heure précise n'existe en raison de l'heure d'été. Au lieu de cela, créez vos propres méthodes pour créer de telles dates. Dans celles-ci, interceptez toutes les exceptions dues à DST et ajustez l'heure avec le décalage de transition. L’heure d’été peut se produire à différentes dates et à différentes heures (même à minuit pour le Brésil) en fonction du fuseau horaire.

1
sebi

En fait, kernel32.dll n'exporte pas SystemTimeToTzSpecificLocation. Il exporte toutefois les deux suivants: SystemTimeToTzSpecificLocalTime et TzSpecificLocalTimeToSystemTime ...

1
Brad

Un seul exemple pour prouver que le temps de traitement est le désordre énorme décrit et que vous ne pouvez jamais être complaisant. À plusieurs endroits sur cette page, les secondes intercalaires ont été ignorées.

Il y a plusieurs années, le système d'exploitation Android utilisait des satellites GPS pour obtenir une référence de temps UTC, mais il ignorait le fait que les satellites GPS n'utilisaient pas de secondes intercalaires. Personne ne s’est aperçu jusqu’à la confusion du Nouvel An, lorsque les Apple utilisateurs du téléphone et le Android utilisateurs du téléphone ont effectué leur décompte à environ 15 secondes d’écart.

Je pense que cela a été corrigé depuis, mais vous ne savez jamais quand ces "détails mineurs" reviendront vous hanter.

1
DavidWalley
  • Jamais, jamais, ne stocke l'heure locale sans son décalage UTC (ou une référence au fuseau horaire) - des exemples expliquant comment ne pas le faire incluent FAT32 et struct tm en C.¹
  • Comprenez qu'un fuseau horaire est une combinaison de
    • un ensemble de décalages UTC (par exemple +0100 en hiver, +0200 en été)
    • règles applicables au moment du basculement (qui peuvent changer dans le temps: par exemple, dans les années 90, l'UE a harmonisé le basculement sur les derniers dimanches de mars et d'octobre à 2 heures, heure normale/03h00, heure avancée; auparavant, ce qui était différent entre les Etats membres).

¹ Certaines implémentations de struct tm enregistrent le décalage UTC, mais cela n’a pas été intégré dans la norme.

1
user149408