web-dev-qa-db-fra.com

Comment stocker des dates répétées en gardant à l'esprit l'heure d'été

Je stocke des événements dans ma base de données. J'ai des dates de début et de fin, tickets_start et tickets_end (pour le moment où la vente de billets commence/se termine réellement - par opposition au début/fin de l'événement réel).

Jusqu'à présent, j'ai construit des méthodes qui font toutes les choses amusantes comme la conversion de la date/heure en GMT avant de l'enregistrer, puis de nouveau dans leur fuseau horaire respectif pour l'affichage.

Je stocke le fuseau horaire dans un champ varchar avec des valeurs comme "America/New_York".

Mais - maintenant, je dois commencer à gérer si l'utilisateur souhaite autoriser la répétition d'événements. Je l'ai déjà fait, et ce n'est pas si grave, mais jamais sur plusieurs fuseaux horaires.

Au début, je pensais que ce ne serait pas grave, mais j'ai ensuite réalisé que - si la date de début initiale était en juillet (comme exemple), et qu'elle se répète chaque mois pendant un an, à un moment donné, l'heure d'été le fera de sorte que la conversion de GMT changera une heure différemment. Un mois, lors de la conversion de 12:00, il le changerait en -5, et le suivant, il le changerait en -4 à cause de l'heure d'été.

Ma pensée actuelle est que je stocke un minuscule `` dst '' (1) pour savoir si les dates de début/fin ont été saisies pendant l'heure d'été, puis je crée une méthode pour modifier l'heure d'une heure si/quand cela est nécessaire.

Mais - j'ai pensé que je demanderais ici dans l'espoir qu'il y ait peut-être une "normale" pour cela ou quelque chose de facile auquel je ne pense pas.

(cakephp 2.4.x)

39
Dave

Tout d'abord, veuillez reconnaître que dans la terminologie moderne, vous devez dire UTC au lieu de GMT. Ils sont pour la plupart équivalents, sauf que l'UTC est défini plus précisément. Réservez le terme GMT pour faire référence à la partie du fuseau horaire au Royaume-Uni qui est en vigueur pendant les mois d'hiver ayant le décalage UTC + 0.

Passons maintenant à votre question. L'UTC n'est pas nécessairement le meilleur moyen de stocker toutes les valeurs de date et d'heure. Cela fonctionne particulièrement bien pour les événements passés , ou pour les événements futurs absolus , mais cela ne fonctionne pas si bien pour les futurs événements locaux - en particulier les futurs récurrents événements.

J'ai écrit à ce sujet sur une autre réponse récemment, et est l'un des rares cas d'exception où l'heure locale a plus de sens que l'UTC. L'argument principal est le "problème du réveil". Si vous réglez votre réveil sur UTC, vous vous réveillerez une heure plus tôt ou plus tard le jour des transitions DST. C'est pourquoi la plupart des gens règlent leur réveil sur l'heure locale.

Bien sûr, vous ne pouvez pas simplement stocker une heure locale si vous travaillez avec des données du monde entier. Vous devez stocker quelques éléments différents:

  • L'heure locale de l'événement récurrent, comme "08:00"
  • Le fuseau horaire dans lequel l'heure locale est exprimée, tel que "America/New_York"
  • Le modèle de récurrence, quel que soit le format, a du sens pour votre application, tel que quotidien, bihebdomadaire ou le troisième jeudi du mois, etc.
  • La prochaine immédiate date et heure UTC équivalente, au mieux que vous puissiez la projeter.
  • Peut-être, mais pas toujours, une liste de dates et d'heures UTC d'événement futur, projetant une période prédéfinie dans le futur (peut-être une semaine, peut-être 6 mois, peut-être un an ou deux, selon vos besoins).

Pour les deux derniers, sachez que l'équivalent UTC de toute date/heure locale peut changer si le gouvernement responsable de ce fuseau horaire décide de changer quoi que ce soit. Puisqu'il y a plusieurs mises à jour de base de données de fuseau horaire chaque année, vous voudrez avoir un plan pour vous abonner aux annonces de mises à jour et mettre à jour votre base de données de fuseau horaire régulièrement. Chaque fois que vous mettez à jour vos données de fuseau horaire, vous devrez recalculer les heures équivalentes UTC de tous les événements futurs.

Il est important d'avoir les équivalents UTC si vous prévoyez d'afficher tout type de liste d'événements couvrant plus d'un fuseau horaire. Ce sont les valeurs que vous interrogerez pour construire cette liste.

Un autre point à considérer est que si un événement est planifié pour une heure locale qui se produit pendant une transition de secours DST, vous devrez décider si l'événement se produit sur la première instance (généralement) ou la deuxième instance (parfois), ou les deux (rarement), et intégrez à votre application un mécanisme garantissant que l'événement ne se déclenche pas deux fois sauf si vous le souhaitez.

Si vous cherchiez une réponse simple - désolé, mais il n'y en a pas. La planification d'événements futurs sur plusieurs fuseaux horaires est une tâche compliquée.

Approche alternative

Quelques personnes m'ont montré une technique où elles utilisent l'heure UTC pour la planification, c'est-à-dire qu'elles choisissent une date de début dans l'heure locale, convertissez-le en UTC à stocker et stockez également l'ID de fuseau horaire. Ensuite, lors de l'exécution, ils appliquent le fuseau horaire pour reconvertir l'heure UTC d'origine en heure locale, puis utilisent cette heure locale pour calculer les autres récurrences, comme s'il s'agissait de celle initialement stockée comme ci-dessus.

Bien que cette technique fonctionne , les inconvénients sont:

  • S'il y a une mise à jour de fuseau horaire qui modifie l'heure locale avant l'exécution de la première instance, elle annulera toute la planification. Cela peut être atténué en choisissant une heure dans le passé pour la "première" instance, de telle sorte que la deuxième instance soit vraiment la première.

  • Si l'heure est vraiment une "heure flottante" qui doit suivre l'utilisateur (comme dans un réveil sur un téléphone portable), vous devez toujours stocker les informations de fuseau horaire pour la zone dans laquelle il a été créé à l'origine - même si ce n'est pas la zone dans laquelle vous voulez courir.

  • Il ajoute une complexité supplémentaire sans aucun avantage. Je réserverais cette technique aux situations où vous pourriez avoir eu un planificateur UTC uniquement dans lequel vous essayez de moderniser la prise en charge du fuseau horaire.

112
Matt Johnson-Pint