Meilleures pratiques pour l'heure d'été et le fuseau horaire [fermé]


2048

J'espère faire de cette question et de ses réponses le guide définitif pour faire face à l'heure d'été, en particulier pour faire face aux changements réels.

Si vous avez quelque chose à ajouter, veuillez

De nombreux systèmes dépendent de l'heure exacte, le problème vient des changements d'heure dus à l'heure d'été - le déplacement de l'horloge vers l'avant ou vers l'arrière.

Par exemple, on a des règles commerciales dans un système de prise de commande qui dépendent de l'heure de la commande - si l'horloge change, les règles pourraient ne pas être aussi claires. Comment le moment de la commande doit-il être conservé? Il existe bien sûr un nombre infini de scénarios - celui-ci est simplement illustratif.

  • Comment avez-vous résolu le problème de l'heure d'été?
  • Quelles hypothèses font partie de votre solution? (recherche de contexte ici)

Aussi important, sinon plus:

  • Qu'avez-vous essayé qui n'a pas fonctionné?
  • Pourquoi ça n'a pas marché?

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

Les réponses générales sont excellentes, mais j'aimerais également voir des détails, surtout s'ils ne sont disponibles que sur une seule plate-forme.


2
@abatishchev - Cette façon GETDATE()sur SQL sera UTC (comme le sera DateTime.Now). Et le serveur ne sera affecté par aucune sorte de modifications DST automatiques.
Odé

4
@Oded: Je peux accepter si "sur le serveur" sera ajouté. Mais cela peut encore affecter d'autres applications qui ont besoin de l'heure locale. Par cela et d'autres raisons, je pense qu'il vaut mieux demander explicitement le temps Utc.
abatishchev

7
L'UTC est préféré à GMT, à la fois parce qu'il est défini plus précisément et parce que les définitions GMT sont gâchées sur certains systèmes d'exploitation. Il est courant que les gens traitent les termes «GMT» et «UTC» comme interchangeables, mais ils ne le sont pas entièrement. Pour presque tous les logiciels / systèmes, utilisez UTC. Voir stackoverflow.com/questions/2292334/…
Chris Johnson

7
@JoshStodola - la « réponse » de Jon Skeet .
Kenny Evitt

1
@Oded, vous ne pouvez pas supposer que le serveur sera en UTC, j'ai vu des serveurs de production où le fuseau horaire était "UTC" mais DST avait été appliqué, donc c'était en fait UTC + 1 pendant plus de la moitié de l'année. Soyez d'accord avec @abatishchev pour être explicite et utiliser DateTime.UtcNowet GETUTCDATE()cela montre également aux autres développeurs que vous y avez réellement pensé
ono2012

Réponses:


940

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

Faire:

  • Chaque fois que vous faites référence à un moment précis dans le temps, conservez 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 connu comme l' heure Zulu ou Z. )
  • Si, au lieu de cela, vous choisissez de conserver une heure en utilisant une valeur d'heure locale, incluez le décalage d'heure locale pour cette heure particulière à partir d'UTC (ce décalage peut changer tout au long de l'année), de sorte que l'horodatage puisse plus tard être interprété sans ambiguïté.
  • Dans certains cas, vous devrez peut-être stocker à la fois l'heure UTC et l'heure locale équivalente. Souvent, cela se fait avec deux champs distincts, mais certaines plates-formes prennent en charge un datetimeoffsettype qui peut stocker les deux dans un seul champ.
  • Lorsque vous stockez des horodatages sous forme de valeur numérique, utilisez le temps Unix - qui est le nombre de secondes entières depuis 1970-01-01T00:00:00Z(à l'exclusion des secondes intercalaires). Si vous avez besoin d'une précision plus élevée, utilisez plutôt des millisecondes. Cette valeur doit toujours être basée sur UTC, sans aucun ajustement de fuseau horaire.
  • Si vous devez ultérieurement modifier l'horodatage, incluez l'ID de fuseau horaire d'origine afin de pouvoir 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 réponse et article de blog .
  • Lorsque vous stockez des dates entières, telles que des anniversaires et des anniversaires, ne convertissez pas en UTC ou tout autre fuseau horaire.
    • Lorsque cela est possible, stockez dans un type de données de date uniquement qui n'inclut pas une heure de la journée.
    • 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 sera ignorée, choisissez 12:00 midi, plutôt que 00:00 minuit comme heure représentative plus sûre ce jour-là.
  • N'oubliez pas que les décalages de fuseau horaire ne sont pas toujours un nombre entier d'heures (par exemple, l'heure standard indienne est UTC + 05: 30 et le Népal utilise 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 DateTimeOffsetc'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 natives fournies par DateTimeet les DateTimeZoneclasses. Soyez prudent lors de l'utilisation DateTimeZone::listAbbreviations()- voir la réponse . Pour garder PHP avec des données Olson à jour, installez périodiquement le paquet PECL timezonedb ; voir réponse .
  • Si vous utilisez C ++, assurez-vous d'utiliser une bibliothèque qui utilise correctement la base de données de fuseau horaire IANA . Il s'agit notamment de cctz , ICU et de la bibliothèque "tz" de Howard Hinnant .
    • N'utilisez pas Boost pour les conversions de fuseau horaire. Bien que son API prétend prendre en charge les identifiants IANA standard (alias "zoneinfo"), elle les associe grossièrement aux données de style POSIX, sans tenir compte de l'historique riche des modifications que chaque zone a pu avoir. (De plus, le fichier n'est plus à jour.)
  • Si vous utilisez Rust, utilisez chrono .
  • La plupart des règles commerciales utilisent l'heure civile, plutôt que l'UTC ou GMT. Par conséquent, prévoyez de convertir les horodatages UTC en fuseau horaire local avant d'appliquer la logique d'application.
  • N'oubliez pas que les fuseaux horaires et les décalages ne sont pas fixes et peuvent changer. Par exemple, les États-Unis et le Royaume-Uni ont historiquement utilisé les mêmes dates pour «avancer» et «reculer». Cependant, en 2007, les États-Unis ont changé les dates auxquelles les horloges sont changé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, 1 en automne), elle est de 4 heures. Soyez conscient des éléments comme celui-ci dans tous les calculs qui impliquent plusieurs zones.
  • Tenez compte du 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 du fuseau horaire) vous devez stocker pour une récupération correcte - voir «Types d'heure» dans cette réponse .
  • Gardez votre OS, votre base de données et vos fichiers tzdata d'application synchronisés, entre eux et le reste du monde.
  • Sur les serveurs, définissez les horloges matérielles et les horloges du système d'exploitation sur UTC plutôt que sur un fuseau horaire local.
  • Indépendamment de la puce précédente, le code côté serveur, y compris les sites Web, ne doit jamais s'attendre à ce que le fuseau horaire local du serveur soit particulier. voir réponse .
  • Préférez travailler avec les fuseaux horaires au cas par cas dans votre code d'application, plutôt que globalement via les paramètres de fichier de configuration ou les valeurs par défaut.
  • Utilisez les services NTP sur tous les serveurs.
  • Si vous utilisez FAT32 , n'oubliez pas que les horodatages sont stockés dans l'heure locale, pas en UTC.
  • Lorsque vous traitez des événements récurrents (émission de télévision hebdomadaire, par exemple), n'oubliez pas que l'heure change avec l'heure d'été et sera différente selon les fuseaux horaires.
  • Toujours interroger les valeurs date-heure en tant que borne inférieure inclusive, borne supérieure exclusive ( >=, <).

Ne pas:

  • Ne confondez pas un "fuseau horaire", comme America/New_Yorkavec un "décalage de fuseau horaire", comme -05:00. Ce sont deux choses différentes. Voir le wiki des balises de fuseau horaire .
  • N'utilisez pas l' Dateobjet JavaScript pour effectuer des calculs de date et d'heure dans des navigateurs Web plus anciens, car ECMAScript 5.1 et inférieur a un défaut de conception qui peut utiliser incorrectement l'heure d'été. (Cela 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 UTC partout". Ce conseil répandu est à courte vue de plusieurs scénarios valides qui sont 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 UTC, mais pas les futures prévisions horaires et les valeurs de date uniquement.)

Essai:

  • Lors des tests, assurez-vous de tester les pays des hémisphères occidental, oriental, nord et sud (en fait dans chaque quart du globe, donc 4 régions), avec les deux DST en cours et non (donne 8), et un pays qui le fait ne pas utiliser l'heure d'été (4 autres pour couvrir toutes les régions, soit 12 au total).
  • Testez la transition de l'heure d'été, c.-à-d. Lorsque vous êtes actuellement à l'heure d'été, sélectionnez une valeur horaire à partir de l'hiver.
  • Tester les cas limites, comme un fuseau horaire UTC + 12, avec l'heure d'été, ce qui rend l'heure locale UTC + 13 en été et même les endroits qui sont 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 au moins les fuseaux horaires d'une demi-heure.

Référence:

Autre:

  • Faites pression sur votre représentant pour mettre fin à l'abomination qu'est l'heure d'été. On peut toujours espérer ...
  • Lobby pour l' heure standard de la Terre

31
L'utilisation de GMT ne résout pas vraiment le problème, vous devez toujours déterminer quel est le bon delta à appliquer, et c'est là que réside toute la complexité. Le delta peut être complexe à déterminer dans les systèmes utilisés par les utilisateurs dans différentes régions (avec des horaires de commutation d'heure d'été différents) ou dans les systèmes affichant des données historiques / futures.
ckarras

10
C'est vrai si tout ce que l'application doit faire est d'afficher l'heure locale actuelle. Mais si nous avons par exemple un serveur en Australie qui doit afficher la date / l'heure d'une transaction au Canada le 2 avril 2006 (c'était la dernière année avant que les règles de changement d'heure d'été changent au Canada) - avez-vous un appel OS qui peut faire DateTime ("2006/04/02 14: 35Z"). ToLocalTime (). WithDaylightSavingRules ("Canada", 2006)?
ckarras

22
Oui, il existe un tel appel de système d'exploitation dans Windows - SystemTimeToTzSpecificLocation. msdn.microsoft.com/en-us/library/ms724949(VS.85).aspx
Michael Madsen

7
@tchrist Peut-être que si vous êtes persévérant, vous le pouvez.
Peter Ajtai

16
Gardez à l'esprit que lorsque vous convertissez des dates futures (même juste demain) en UTC, vous perdez toujours quelque chose. Par exemple, vous avez utilisé un décalage connu pour effectuer cette conversion, mais comme la date est dans le futur, il est toujours possible que le groupe qui définit ces règles modifie ces règles. En outre, il est pratiquement impossible de convertir certaines dates futures en UTC car les heures d'été ne sont pas connues avant cette année (certains pays fixent les dates chaque année, pas plus de 10 ans à l'avance ou en fonction de règles définies).
eselk

319

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

Types de fois

Vous devez considérer quatre moments différents:

  1. Heure de l'événement: par exemple, l'heure à laquelle un événement sportif international se produit, ou un couronnement / décès / etc. Cela dépend du fuseau horaire de l'événement et non du spectateur.
  2. Heure de la télévision: par exemple, une émission de télévision particulière est diffusée à 21 heures, heure locale, dans le monde entier. Important lorsque vous envisagez de publier les résultats (disons American Idol) sur votre site Web
  3. Temps relatif: par exemple: cette question a une prime ouverte se fermant dans 21 heures. C'est facile à afficher
  4. Heure récurrente: par exemple: une émission de télévision a lieu tous les lundis à 21 h, même lorsque l'heure d'été change.

Il y a aussi une heure historique / alternative. Ce sont ennuyeux car ils peuvent ne pas correspondre à l'heure standard. Par exemple: dates juliennes, dates selon un calendrier lunaire sur Saturne, le calendrier Klingon.

Le stockage des horodatages de début / fin en UTC fonctionne bien. Pour 1, vous avez besoin d'un nom de fuseau horaire d'événement + décalage 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é pour chaque téléspectateur (il est possible de le dériver de l'IP si vous êtes en crise). Pour 3, stockez en secondes UTC et pas besoin de fuseaux horaires. 4 est un cas spécial de 1 ou 2 selon qu'il s'agit d'un événement global ou local, mais vous devez également stocker un élément créé à l' horodatage afin de savoir si une définition de fuseau horaire a changé 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

  • Stockez toujours le temps en UTC
  • Conversion en heure locale affichée (heure locale définie par l'utilisateur qui regarde les données)
  • Lors du stockage d'un fuseau horaire, vous avez besoin du nom, de l'horodatage et du décalage. Cela est nécessaire car les gouvernements modifient parfois la signification de leur fuseau horaire (par exemple: le gouvernement américain a changé les dates d'heure d'été), et votre application doit gérer les choses avec élégance ... par exemple: l'horodatage exact lorsque les épisodes de LOST sont affichés avant et après les règles d'heure d'été modifié.

Décalages et noms

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

La finale de la coupe du monde de football s'est déroulée en Afrique du Sud (UTC + 2 - SAST) le 11 juillet 2010 à 19h00 UTC.

Avec ces informations, nous pouvons historiquement déterminer l'heure exacte à laquelle la finale du WCS 2010 a eu lieu, même si la définition du fuseau horaire sud-africain change, et être en mesure d'afficher cela aux téléspectateurs dans leur fuseau horaire local au moment où ils interrogent la base de données.

Le temps du système

Vous devez également synchroniser votre système d'exploitation, votre base de données et vos fichiers tzdata d'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 sur laquelle vous dépendez n'ait pas correctement géré une modification TZ.

Assurez-vous que les horloges matérielles sont définies sur UTC et si vous exécutez des serveurs dans le monde entier, assurez-vous que leurs systèmes d'exploitation sont également configurés pour utiliser UTC. Cela devient évident lorsque vous devez copier des fichiers journaux Apache pivotés toutes les heures à 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'avez pas à faire de calcul de date dans votre tête lorsque vous passez d'une boîte à l'autre et que vous devez comparer les horodatages.

Exécutez également ntpd sur toutes les boîtes.

Clients

Ne faites jamais confiance à l'horodatage que vous obtenez d'un ordinateur client comme valide. Par exemple, les en-têtes Date: HTTP ou un Date.getTime()appel javascript . Ceux-ci sont parfaits lorsqu'ils sont utilisés comme identifiants opaques ou lorsque vous effectuez des calculs de date au cours d'une seule session sur le même client, mais n'essayez pas de comparer 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 de travail pour leur horloge BIOS.

Trivia

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

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

Ok, je pense que j'ai fini.


6
Cette réponse a quelques bons points, je voulais surtout souligner cette partie "Heure récurrente: par exemple: une émission de télévision a lieu tous les lundis à 21 heures, même lorsque l'heure d'été change". beaucoup des aspects délicats de la gestion des fuseaux horaires. Cependant, la gestion des «événements récurrents» qui franchissent les barrières DST devient beaucoup plus difficile.
Jared Hales

45
+1 pour le Trivia. Garder le contenu intéressant rend cette tâche plus agréable, ce qui peut entraîner une productivité accrue :)
Chris

4
Beaucoup de bonnes choses dans cette réponse, mais quelques problèmes. 1) De nombreuses abréviations de fuseaux horaires sont ambiguës. voir ici 2) Vous ne voulez pas toujours stocker en UTC. La plupart du temps - oui, mais le contexte compte. Selon vos termes, l' heure de la télévision ne serait pas stockée en UTC. De plus, il est parfois illégal ou contraire à la politique de ne pas stocker l'heure locale - c'est là que des choses comme DateTimeOffset(ou équivalent) sont utiles. Sinon, bonne rédaction.
Matt Johnson-Pint

1
Donc, tout le monde convient que la bibliothèque Joda est de loin le meilleur outil disponible pour le travail. Cependant, nous devons continuer à mettre à jour (reconstruire) le fichier JAR JAR conformément à cet article ( joda.org/joda-time/tz_update.html ) afin de rester à jour avec les dernières informations de fuseau horaire. Existe-t-il un moyen standard de télécharger les dernières données de fuseau horaire à partir du site Web de l'IANA ( iana.org/time-zones ) et de reconstruire la bibliothèque joda? En d'autres termes, est-il possible d'automatiser ce processus plutôt que de le faire manuellement?
saravana_pc

2
Les anecdotes néerlandaises semblent légitimes. ietf.org/rfc/rfc3339.txt section 5.8. A mi-chemin, on pensait que quelqu'un nous tirait la jambe.
ruffin

89

C'est une question importante et étonnamment difficile. La vérité est qu'il n'y a pas de norme complètement satisfaisante pour la persistance du temps. Par exemple, la norme SQL et le format ISO (ISO 8601) ne sont clairement pas suffisants.

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

Un instant "physique" du temps est un point de la chronologie universelle continue avec lequel la physique traite (en ignorant la relativité, bien sûr). Ce concept peut être adéquatement codé en UTC, par exemple (si vous pouvez ignorer les secondes intercalaires).

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

La question est confuse parce que nous parlons de ces types d'événements de manière interchangeable et parce que l'époque civile est sujette à des changements politiques. Le problème (et la nécessité de distinguer ces concepts) devient plus évident pour les événements futurs. Exemple (tiré de ma discussion ici .

John enregistre dans son calendrier un rappel pour un événement à l'heure 2019-Jul-27, 10:30:00, TZ = Chile/Santiago, (qui a décalé GMT-4, donc cela correspond à UTC 2019-Jul-27 14:30:00). Mais un jour à l'avenir, le pays décide de changer la compensation TZ en GMT-5.

Maintenant, quand le jour viendra ... 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'y a pas de bonne réponse, à moins que l'on ne sache ce que Jean voulait dire conceptuellement quand il a dit au calendrier "Veuillez me téléphoner à 2019-Jul-27, 10:30:00 TZ=Chile/Santiago".

Voulait-il dire un «rendez-vous civil» («quand les horloges de ma ville indiquent 10 h 30»)? 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, disons, "quand la prochaine éclipse solaire se produira". Dans ce cas, la réponse B) est la bonne.

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


1
Un autre point à considérer que je n'ai pas vu abordé dans les API est que même lorsque l'heure et le fuseau horaire sont donnés, il y a au moins deux significations plausibles pour par exemple "13: 00: 00EDT". Il pourrait s'agir de quelque chose qui est connu pour s'être produit à 13 heures, heure locale, qui était censée être l'heure avancée de l'Est, ou quelque chose qui s'est produit au moment où l'heure de l'Est a frappé 13h00, ce qui serait ont eu lieu dans un endroit observant l'heure avancée de l'Est. Si l'on a plusieurs horodatages où les informations de fuseau horaire peuvent être erronées (par exemple, les fichiers de l'appareil photo numérique) ...
supercat

1
... savoir s'ils reflètent une heure locale précise ou une heure mondiale peut être important pour déterminer comment les corriger.
supercat

3
Clairement, John veut A) parce que les gens vont travailler à 8h30, quel que soit l'heure d'été ou le fuseau horaire actuellement. S'ils passent à l'heure d'été, ils iront travailler à 8h30, lorsqu'ils sortiront de l'heure d'été, ils iront travailler à 8h30. Si le pays décide de passer à un autre fuseau horaire, ils iront travailler à 8h30 tous les jours
Gianluca Ghettini

59

Faites une séparation architecturale claire des préoccupations - pour savoir exactement quel niveau interagit avec les utilisateurs, et doit changer la date-heure pour / de la représentation canonique (UTC). La date-heure non UTC est la présentation (suit le fuseau horaire local des utilisateurs), l' heure UTC est le modèle (reste unique pour les niveaux principaux et intermédiaires).

Décidez également quel est votre public réel, ce que vous n'avez pas à servir et où tracez-vous la ligne . Ne touchez pas aux calendriers exotiques à moins que vous ayez réellement des clients importants là-bas, puis envisagez des serveurs distincts pour l'utilisateur uniquement pour cette région.

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

S'il y a des obligations d'audit historiques impliquées (comme dire exactement quand Jo en AZ a payé une facture il y a 2 ans en septembre), gardez à la fois l'heure UTC et locale pour l'enregistrement (vos tables de conversion changeront au fil du temps).

Définissez le fuseau horaire de référence pour les données qui arrivent en vrac - comme les fichiers, les services Web, etc. Supposons que la société East Coast possède un centre de données en Californie - vous devez demander et savoir ce qu'elle utilise comme standard au lieu de supposer l'un ou l'autre.

Ne vous fiez pas aux décalages de fuseau horaire intégrés dans la représentation textuelle de la date-heure et n'acceptez pas de les analyser et de les suivre. Au lieu de cela, demandez toujours que le fuseau horaire et / ou le fuseau de référence soient définis explicitement . Vous pouvez facilement recevoir l'heure avec 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 juste été exportés vers un serveur qui est en PST.


40

Vous devez connaître la base de données Olson tz , qui est disponible sur 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 concernant le moment (et l'opportunité) de basculer entre l'heure d'hiver et d'été (heure d'été et heure d'été) dans différents pays du monde. En 2009, la dernière version était des années 2009; en 2010, c'était 2010n; en 2011, c'était 2011n; fin mai 2012, la sortie était 2012c. Notez qu'il existe un ensemble de codes pour gérer les données et les données de fuseau horaire elles-mêmes, 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 des noms de fuseau horaire tels que America / Los_Angeles (et des synonymes tels que US / Pacific).

Si vous devez suivre les 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 - avec 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 à l'UTC à l'heure et le nom du fuseau horaire; cela peut faire une différence plus tard. En outre, sachant qu'il s'agit actuellement du 2010-03-28T23: 47: 00-07: 00 (États-Unis / Pacifique) peut ou non vous aider à interpréter la valeur 2010-11-15T12: 30 - qui est probablement spécifiée dans PST ( Pacific Standard Time) plutôt que PDT (Pacific Daylight Saving Time).

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


Les données Olson ont changé, en partie parce que AD Olson va bientôt prendre sa retraite, et en partie parce qu'il y a eu une action en justice (maintenant rejetée) contre les responsables pour violation du droit d'auteur. La base de données de fuseau horaire est désormais gérée sous les auspices de l' IANA , Internet Assigned Numbers Authority, et il y a un lien sur la première page vers «Time Zone Database» . La liste de diffusion de discussion est maintenant tz@iana.org; la liste des annonces est tz-announce@iana.org.


12
La base de données Olson contient également des données historiques , ce qui la rend particulièrement utile pour la gestion de l'heure d'été. Par exemple, il sait qu'une valeur UTC correspondant au 31 mars 2000 aux États-Unis n'est pas en DST, mais une valeur UTC correspondant au 31 mars 2008 aux États-Unis l'est.
Josh Kelley

3
Le consortium Unicode maintient une correspondance entre les ID de zone de tome Olson et les ID de fuseau horaire Windows: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Josh Kelley

Lien mis à jour pour la page du consortium Unicode: unicode.org/repos/cldr-tmp/trunk/diff/supplemental/…
Span

Où peut-on trouver des informations sur l'analyse des fichiers Olson? Je veux le compiler dans une table db, mais je n'arrive pas à comprendre comment dois-je lire les fichiers
shealtiel

@gidireich: les informations principales se trouvent avec les données, et ce n'est pas facile à comprendre. La documentation principale pour cela se trouve dans la zic.8page de manuel (ou zic.8.txt). Vous aurez besoin du tzcode2011i.tar.gzfichier plutôt que, ou aussi, du tzdata2011i.tar.gzfichier pour obtenir ces informations.
Jonathan Leffler

26

En général, incluez le décalage horaire local (y compris le décalage DST) dans les horodatages stockés: UTC seul ne suffit pas si vous souhaitez afficher ultérieurement l'horodatage dans son fuseau horaire d'origine (et le réglage DST).

Gardez à l'esprit 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 (temps Unix, décalage en minutes) ou ISO 8601 .


5
Pour l'affichage, le décalage est parfait. Si vous souhaitez apporter des modifications, le décalage n'est toujours pas suffisant. Vous devez également connaître le fuseau horaire car la nouvelle valeur peut nécessiter un décalage différent.
Matt Johnson-Pint

23

Traverser la frontière du «temps informatique» et du «temps des gens» est un cauchemar. Le principal étant qu'il n'existe aucune sorte de norme pour les règles régissant les fuseaux horaires et les heures d'été. Les pays sont libres de modifier leur fuseau horaire et leurs règles d'heure d'été à tout moment, et ils le font.

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

Les fuseaux horaires ne doivent pas être des différences d'une 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 veut dire que:

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

sont tous en même temps, et pourtant 3 jours différents!

Il n'y a pas non plus de norme claire sur les abréviations des fuseaux horaires et sur la façon dont ils changent lorsqu'ils sont en DST, vous vous retrouvez avec des choses comme ceci:

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

Le meilleur conseil est de vous éloigner autant que possible des heures locales et de vous en tenir à UTC où vous le pouvez. Convertissez uniquement en heure locale au dernier moment possible.

Lors des tests, assurez-vous de tester les pays des hémisphères occidentaux et orientaux, avec à la fois l'heure d'été en cours et non et un pays qui n'utilise pas l'heure d'été (6 au total).


En ce qui concerne Israël - c'est à moitié vrai. Bien que l'heure du changement d'heure d'été ne soit pas une date spécifique dans le calendrier julien - il existe une règle basée sur le calendrier hébreu (il y a eu un changement en 2014). Quoi qu'il en soit, l'idée générale est correcte - ces choses pourraient changer et changent de temps en temps
Yaron U.

1
Aussi, AST = Atlantic Standard Time. Quant au «meilleur conseil», il est correct comme point de départ, mais vous devez lire le reste de cette page et dire une petite prière, et vous pourriez bien faire les choses pendant un certain temps.
DavidWalley

20

Pour PHP:

La classe DateTimeZone en PHP> 5.2 est déjà basée sur la base de données Olson que d'autres mentionnent, donc si vous effectuez des conversions de fuseau horaire en PHP et non dans la base de données, vous êtes exempté de travailler avec les fichiers Olson (difficiles à comprendre).

Cependant, PHP n'est pas mis à jour aussi souvent que la base de données Olson, donc l'utilisation de conversions de fuseau horaire PHP peut vous laisser des informations DST obsolètes et influencer l'exactitude de vos données. Bien que cela ne devrait pas se produire fréquemment, cela peut se produire et se produira si vous avez une large base d'utilisateurs dans le monde.

Pour faire face au problème ci-dessus, utilisez le package timezonedb pecl . Sa fonction est de mettre à jour les données de fuseau horaire de PHP. Installez ce package aussi souvent qu'il est mis à jour. (Je ne sais pas si les mises à jour de ce package suivent exactement les mises à jour Olson, mais il semble être mis à jour à une fréquence qui est au moins très proche de la fréquence des mises à jour Olson.)


18

Si votre conception peut l'adapter, évitez la conversion de l'heure locale tous ensemble!

Je sais que pour certains cela peut sembler fou, mais pensez à UX: les utilisateurs traitent des dates proches (aujourd'hui, hier, lundi prochain) plus rapidement que les dates absolues (2010.09.17, vendredi 17 septembre) en un coup d'œil. Et quand on y pense plus, la précision des fuseaux horaires (et DST) est plus importante plus la date est proche now(), donc si vous pouvez exprimer des dates / heures dans un format relatif pendant +/- 1 ou 2 semaines, le reste de les dates peuvent être UTC et cela n'aura pas trop d'importance pour 95% des utilisateurs.

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

Cela peut également s'appliquer à la saisie utilisateur (mais généralement de manière plus limitée). La sélection dans une liste déroulante qui n'a que {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 dates sont parmi les composants les plus douloureux du remplissage de formulaires. Bien sûr, cela ne fonctionnera pas dans tous les cas, mais vous pouvez voir qu'il suffit d'un peu de conception intelligente pour le rendre très puissant.


16

Bien que je ne l'ai pas essayé, une approche des ajustements de fuseau horaire que je trouverais convaincante serait la suivante:

  1. Stockez tout en UTC.

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

Dans le tableau, stocker une liste des dates et des heures l'heure locale changé, et combien. Le nombre de régions dans le tableau et le nombre de dates dépendent de la plage de dates et des régions du monde que vous devez prendre en charge. Considérez cela comme s'il s'agissait d'une date "historique", même si les dates devraient inclure l'avenir dans une certaine limite pratique.

Lorsque vous devez calculer l'heure locale de n'importe quelle heure UTC, procédez comme suit:

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

Vous souhaiterez 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 frapper la base de données.

Ces données peuvent être distillées à partir de la 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 de nouvelles régions ou plages de dates.
  2. Vous n'avez pas à prendre en charge chaque plage de dates ou de régions, vous pouvez les ajouter au besoin.
  3. Les régions ne doivent pas correspondre directement aux frontières géopolitiques et pour éviter la duplication des 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 de états, pays, etc.
  4. Pour les situations comme les États-Unis où la date 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. Étant donné que le champ StartDateTime peut également stocker une heure, l'heure de changement standard à 2 h 00 est gérée facilement.
  6. Pas partout dans le monde utilise un DST d'une heure. Cela gère ces cas facilement.
  7. Le tableau de données est multiplateforme et pourrait être un projet open source distinct qui pourrait être utilisé par les développeurs qui utilisent presque n'importe quelle plate-forme de base de données ou langage de programmation.
  8. Cela peut être utilisé pour les décalages qui n'ont rien à voir avec les fuseaux horaires. Par exemple, les ajustements de 1 seconde qui se produisent de temps en temps pour ajuster la rotation de la Terre, les ajustements historiques vers et dans le 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 tirer parti des données sans avoir à parcourir le code logique métier.
  10. Cela gère également les décalages de fuseau horaire si vous le souhaitez, et peut même prendre en compte les cas historiques spéciaux où 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 comme: "Quelle est la différence d'heure locale entre Yuma, Arizona et Seattle, Washington le 2 février 1989 à 5h00?" (Il suffit de soustraire 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 en GMT ne sont pas parfaites, car tout changement d'heure d'été qui a un décalage négatif par rapport à l'horloge répète une heure locale donnée. Ce n'est pas un moyen facile de gérer cela, je le crains, ce qui est une des raisons pour lesquelles l'heure locale est une mauvaise nouvelle en premier lieu.


8
Votre idée de base de données a déjà été implémentée en tant que base de données Olson. Bien que l'heure d'été crée un chevauchement spécifiant le fuseau horaire spécifique à la lumière du jour, cela peut aider à résoudre le problème. 2:15 EST et 2:15 EDT sont des heures différentes. Comme indiqué dans d'autres articles, la spécification de l'offset résout également l'ambiguïté.
BillThor

5
Le gros problème avec la conservation de votre propre base de données est de la maintenir à jour. Olson et Windows sont gérés pour vous. J'ai eu plus d'un cas de mauvaises transitions DST parce que les tables étaient obsolètes. Les extraire entièrement et s'appuyer sur un cadre ou une base de données au niveau du système d'exploitation est beaucoup plus fiable.
Matt Johnson-Pint

4
Ne créez pas votre propre base de données : comptez toujours sur l'API du système!
Alex

15

J'ai récemment rencontré un problème dans une application Web où, sur un post-back Ajax, le datetime revenant à mon code côté serveur était différent du datetime servi.

Cela avait très probablement à voir avec mon code JavaScript sur le client qui a créé la date de publication sur le client sous forme de chaîne, car JavaScript ajustait le fuseau horaire et l'heure d'été, et dans certains navigateurs, le calcul du moment où appliquer l'heure d'été semblait différent des autres.

À la fin, j'ai choisi de supprimer entièrement les calculs de date et d'heure sur le client, et j'ai posté sur mon serveur une clé entière qui a ensuite été traduite à l'heure actuelle sur le serveur, pour permettre des transformations cohérentes.

Mon apprentissage: n'utilisez pas les calculs de date et d'heure JavaScript dans les applications Web, sauf si vous en avez ABSOLUMENT besoin.


Javascript s'exécute sur la machine client, pas sur la machine serveur. Le datetime de base de Javascript est le datetime du client, pas le datetime du serveur.
BalusC

Salut BalusC. Je comprends cela (de mon message d'origine: "script javacode sur le client qui a construit la date ..."). Mon problème était que certaines machines clientes traitaient l'heure d'été d'une manière et d'autres d'une autre manière. Par conséquent, j'ai déplacé tout ce traitement côté serveur pour éviter la bizarrerie du navigateur
Joon

@ Joon — et il y a des bogues dans les implémentations javascript que vous ne pouvez pas détecter ou autoriser. Alors oui, n'utilisez jamais les calculs de date ECMAScript côté client pour les choses qui comptent (bien que vous puissiez faire un très bon travail autrement).
RobG

14

J'ai touché ceci 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épendant du gaz)

Les journées de 23 et 25 heures sont difficiles à gérer, tout comme les quarts de 8 heures qui prennent 7 heures ou 9 heures. Le problème est que vous constaterez que chaque client, ou même département du client, a des règles différentes qu'il a créées (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 qu'il n'ait payé pour votre logiciel «standard». Il est très rare de trouver un client qui pense à ce type de problème dès le départ lors de l'achat d'un logiciel.

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


6
Ma copine, une infirmière, travaille la nuit et ils doivent écrire le fuseau horaire pendant le passage à l'heure d'été. Par exemple, 2AM CST vs 2AM CDT
Joe Phillips

1
Oui, cela est courant: lorsque vous calculez une moyenne quotidienne (civile), vous devez faire face à des jours de 23, 24 ou 25 heures. Par conséquent, lorsque vous calculez ajouter 1 jour, ce n'est pas ajouter 24 heures ! Deuxièmement, n'essayez pas de créer votre propre code de fuseau horaire; utilisez uniquement l'API des systèmes. Et n'oubliez pas de mettre à jour chaque système déployé afin d'obtenir la base de données de fuseau horaire à jour .
Alex

12

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

  • Côté serveur, utilisez UTC
  • Côté client, utilisez Olson
    • Raison: les décalages UTC ne sont pas à l'heure d'été (par exemple, New York est EST (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) Avoir une zone définie par l'utilisateur (plus sûr)
      • 2) Zone de détection automatique

Le reste est juste une conversion UTC / locale en utilisant vos bibliothèques datetime côté serveur. Bon pour aller ...


2
C'est un bon conseil comme point de départ, mais cela dépend totalement de l'application. Cela peut être bien pour un site Web convivial, mais s'il y a un aspect juridique / juridictionnel / financier à votre demande que quelqu'un pourrait poursuivre (j'ai travaillé sur plusieurs), alors c'est une simplification excessive car il existe différents types de ' comme indiqué ailleurs sur cette page.
DavidWalley

12

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

Il est généralement conseillé de définir le fuseau horaire du serveur sur UTC. C'est en effet une bonne pratique exemplaire, mais c'est là comme un pansement pour les applications qui ne suivent pas d'autres bonnes 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 cette application. Cependant, la vraie solution serait que l'application se connecte en utilisant UTC pour commencer.

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

Dans certaines langues, le fuseau horaire local peut facilement se glisser dans le code d'application. Par exemple, la DateTime.ToUniversalTimeméthode dans .NET convertira du fuseau horaire local en UTC et la DateTime.Nowpropriété renvoie l'heure actuelle dans le fuseau horaire local. En outre, le Dateconstructeur en JavaScript utilise le fuseau horaire local de l'ordinateur. Il existe de nombreux 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, comme les applications de bureau, les applications mobiles et le JavaScript côté client.


11

Gardez vos serveurs définis sur UTC et assurez-vous qu'ils sont tous configurés pour ntp ou l'équivalent.

L'UTC évite les problèmes d'heure d'été et les serveurs désynchronisés peuvent entraîner des résultats imprévisibles qui prennent un certain temps à diagnostiquer.


9

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 de l'heure locale (qui incluent l'heure d'été - voir l' article msdn ). Vous avez brûlé sur celui-là.


Bon point. NTFS n'a pas ce problème, mais certaines personnes utilisent toujours FAT32 - en particulier sur les clés USB.
Matt Johnson-Pint

7

Une autre chose, assurez-vous que les correctifs d'heure d'été mis à jour sont appliqués aux serveurs.

L'année dernière, nous avons eu une situation où nos temps étaient systématiquement dépassés d'une heure pendant une période de trois semaines pour les utilisateurs nord-américains, même si nous utilisions un système basé sur UTC.

Il s'avère finalement que ce sont les serveurs. Ils avaient juste besoin d'un correctif à jour appliqué ( Windows Server 2003 ).


6

DateTimeZone::listAbbreviations()Sortie de PHP

Cette méthode PHP renvoie un tableau associatif contenant des fuseaux horaires «majeurs» (comme CEST), qui en eux-mêmes contiennent des fuseaux horaires «géographiques» plus spécifiques (comme 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 différentes configurations offset / DST (y compris les configurations historiques) de chaque fuseau horaire sont incluses!

Par exemple, Europe / Amsterdam peut être trouvé six fois dans la sortie de cette fonction. Deux occurrences (offset 1172/4772) sont pour le temps d'Amsterdam utilisé jusqu'en 1937; deux (1200/4800) sont pour l'époque qui a été utilisée entre 1937 et 1940; et deux (3600/4800) correspondent au temps utilisé depuis 1940.

Par conséquent, vous ne pouvez pas compter sur les informations de décalage / DST renvoyées par cette fonction comme étant actuellement correctes / utilisées!

Si vous voulez connaître le décalage / DST actuel d'un certain fuseau horaire, vous devrez faire quelque chose comme ceci:

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

5

S'il vous arrive de maintenir des systèmes de base de données qui fonctionnent avec l'heure d'été active, vérifiez soigneusement s'ils doivent être arrêtés pendant la transition à l'automne. Mandy DBS (ou d'autres systèmes également) n'aime pas passer deux fois le même point dans l'heure (locale), ce qui se produit exactement lorsque vous revenez en arrière à l'automne. SAP a résolu cela avec une solution de contournement (à mon humble avis) - au lieu de revenir en arrière, ils ont juste laissé l'horloge interne fonctionner à la moitié de la vitesse habituelle pendant deux heures ...


4

Utilisez-vous le framework .NET ? Si c'est le cas, permettez-moi de vous présenter le type DateTimeOffset , ajouté avec .NET 3.5.

Cette structure contient à la fois un DateTimeet un décalage ( TimeSpan), qui spécifie la différence entre la DateTimeOffsetdate et l'heure de l' instance et le temps universel coordonné (UTC).

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

  • La DateTimeOffset.UtcNowméthode statique renvoie une DateTimeOffsetinstance composée de l'heure actuelle en UTC (comme si vous étiez à Greenwich).

Les autres types utiles sont les classes TimeZone et TimeZoneInfo .


Ce n'est pas une solution au problème présenté.
caradrye le

4

Pour ceux qui ont du mal avec cela sur .NET , voyez si l'utilisation DateTimeOffsetet / ou en TimeZoneInfovaut la peine.

Si vous souhaitez utiliser les fuseaux horaires IANA / Olson ou si les types intégrés sont insuffisants pour vos besoins, consultez Noda Time , qui propose une API de date et d'heure beaucoup plus intelligente pour .NET.


4

Les règles commerciales devraient toujours fonctionner sur le temps civil (sauf si une législation stipule le contraire). Soyez conscient que le temps civil est un gâchis, mais c'est ce que les gens utilisent donc c'est ce qui est important.

En interne, conservez les horodatages dans quelque chose comme civil-time-seconds-from-epoch. L' époque n'a pas d'importance particulière (je préfère l' époque Unix ) mais cela rend les choses plus faciles que l'alternative. Imaginez que les secondes intercalaires n'existent que 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 où les règles DST doivent être appliquées; les règles changent fréquemment (au niveau mondial, plusieurs fois par an; blâmer les politiciens), vous devez donc vous assurer de ne pas coder en dur la cartographie. La base de données TZ d'Olson est inestimable.


3
Le problème ici est que l'heure civile (alias l'heure du calendrier) ne représente pas correctement un seul instant dans le temps. Si vous adoptez l'approche des secondes depuis l'époque, allez-vous vraiment tenir compte de chaque instant qui a été ignoré ou rembobiné pour les transitions de l'heure d'été? Probablement pas. La base Epoch ne fonctionne qu'avec UTC ou une autre référence fixe à temps instantané.
Matt Johnson-Pint

@MattJohnson D'où la partie "règles métier". Si les règles stipulent que quelque chose se produit à 2h30 du matin (ou à n'importe quelle heure), cela se produira deux fois par jour par an et jamais par jour. C'est ce que le client attend s'il ne clarifie pas la règle.
user253751

Garder les horodatages internes en temps civil peut être très délicat. Garder cela comme secondes depuis qu'une époque est encore plus délicate, je dirais carrément périlleux. Je suis sûr qu'il y a des gens qui le font, et il pourrait être possible de le faire fonctionner correctement la plupart du temps si vous êtes très prudent, mais cela ne peut pas être considéré comme une meilleure pratique ou une recommandation générale.
Steve Summit

2

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

Conservez toujours le temps selon une norme unifiée qui n'est pas affectée par l'heure d'été. GMT et UTC ont été mentionnés par différentes personnes, bien que UTC semble être mentionné le plus souvent.

Pour (presque) toutes les applications informatiques pratiques, l'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 horaire local tel quel (y compris le décalage DST) lors du stockage des horodatages.

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


1
Le décalage d'heure locale vous permettra de recréer l '«heure du mur» d'origine de l'événement. Si vous ne stockez pas ce champ supplémentaire, ces données sont perdues.
nogridbag

Oui, sauf que les décalages UTC et GMT sont inverses. Par exemple, l'UTC-0700 est identique à GMT + 0700. Vraiment, tout le numérique devrait utiliser l'UTC de nos jours.
Matt Johnson-Pint

1
@Matt: êtes-vous sûr que les décalages UTC et GMT sont inverses? où puis-je lire à ce sujet?
Reto Höhener

En fait, je pense que je me trompais avant. GMT et UTC ne sont pas inversés eux-mêmes. C'est qu'il existe des implémentations qui les montrent en sens inverse, comme la base de données IANA / Olson / TZDB. Voyez ici . Un autre domaine dans lequel vous voyez des décalages inverses est la fonction getTimezoneOffset () de javascript.
Matt Johnson-Pint

@MattJohnson: Ce sont des hacks et devraient être supprimés.
Alix Axel

2

Voici mon expérience: -

(Ne nécessite aucune bibliothèque tierce)

  • Côté serveur, stockez les heures au format UTC afin que toutes les valeurs de date / heure dans 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 e-mails envoyés à l'utilisateur, vous devez afficher les heures en fonction de l'utilisateur. Pour cette question, vous devez avoir le décalage du fuseau horaire de l'utilisateur afin que vous puissiez ajouter ce décalage à la valeur UTC de votre base de données, ce qui entraînera l'heure locale de l'utilisateur. Vous pouvez soit décaler le 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 fonction JavaScript getTimezoneOffset () est une norme depuis la version 1.0 et compatible avec tous les navigateurs. (Réf: http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp )

Cela ne fonctionne pas lorsque vous envisagez des modifications d'heure d'été. getTimezoneOffsetrenvoie le décalage pour la date et l'heure auxquelles vous l'appelez. Ce décalage peut changer lorsqu'un fuseau horaire passe dans ou hors de l'heure d'été. Voir "fuseau horaire! = Offset" dans le wiki des balises de fuseau horaire .
Matt Johnson-Pint

1
Si vous souhaitez stocker une alarme telle que "faire quelque chose à 10h00", vous ne pouvez pas la stocker en UTC, en raison des décalages DST. Vous devez le stocker par rapport à l'heure locale.
Alex

2

La vidéo de Tom Scott sur les fuseaux horaires sur YouTube sur la chaîne Computerphile a é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 avec l'Australie et la Nouvelle-Zélande,
  • Cisjordanie , où 2 populations de personnes suivent des fuseaux horaires différents,
  • Le 18e siècle passe du calendrier julien au calendrier grégorien (ce qui s'est produit au 20e siècle en Russie).

1

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


1

Ne vous fiez jamais uniquement à des constructeurs comme

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

Ils peuvent lever des exceptions lorsqu'une certaine date-heure n'existe pas en raison de l'heure d'été. Au lieu de cela, créez vos propres méthodes pour créer de telles dates. Dans eux, interceptez toutes les exceptions qui se produisent en raison de l'heure d'été et ajustez le temps nécessaire 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) selon le fuseau horaire.


1

Un seul exemple pour prouver que le temps de traitement est le gros gâchis 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 temporelle UTC, mais ignorait le fait que les satellites GPS n'utilisaient pas de secondes intercalaires. Personne n'a remarqué jusqu'à ce qu'il y ait de la confusion le soir du Nouvel An, lorsque les utilisateurs de téléphones Apple et les utilisateurs de téléphones Android ont fait leur compte à rebours à environ 15 secondes d'intervalle.

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


1
  • Jamais, jamais stocker l'heure locale sans son décalage UTC (ou une référence au fuseau horaire) - des exemples de la façon de ne pas le faire incluent FAT32 et struct tmen C.¹
  • Comprendre qu'un fuseau horaire est une combinaison de
    • un ensemble de décalages UTC (par exemple +0100 en hiver, +0200 en été)
    • règles concernant le moment où le basculement a lieu (qui peut changer au fil du temps: par exemple, dans les années 90, l'UE a harmonisé le basculement comme ayant lieu les derniers dimanches de mars et octobre, à 02h00, heure standard / 03h00, heure d'été; auparavant, cela différait entre les États membres).

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


-4

En traitant des bases de données (en particulier MySQL , mais cela s'applique à la plupart des bases de données), j'ai eu du mal à stocker UTC.

  • Les bases de données fonctionnent généralement avec le serveur datetime par défaut (c'est-à-dire, CURRENT_TIMESTAMP).
  • Vous ne pourrez peut-être pas modifier le fuseau horaire du serveur.
  • Même si vous pouvez modifier le fuseau horaire, vous pouvez disposer d'un code tiers qui s'attend à ce que le fuseau horaire du serveur soit local.

J'ai trouvé plus facile de simplement stocker le datetime du serveur dans la base de données, puis de laisser la base de données reconvertir le datetime stocké en UTC (c'est-à-dire UNIX_TIMESTAMP ()) dans les instructions SQL. Après cela, vous pouvez utiliser le datetime comme UTC dans votre code.

Si vous contrôlez à 100% le serveur et tout le code, il est probablement préférable de changer le fuseau horaire du serveur en UTC.


L'heure locale (l'heure du serveur) peut être ambiguë lors des transitions de l'heure d'été de style "repli". Ce n'est pas fiable à utiliser comme vous l'avez décrit. Il peut y avoir plus d'une heure UTC que l'heure locale du serveur peut représenter.
Matt Johnson-Pint

L'heure locale est parfaitement correcte si le serveur est situé dans un fuseau horaire sain, c'est-à-dire qui ne fait pas l'heure d'été.
sayap
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.