web-dev-qa-db-fra.com

Qu'est-ce qu'un cas d'utilisation valide pour utiliser TIMESTAMP WITHOUT TIME ZONE?

Il existe une réponse longue et assez élucidante sur les différences entre

  • TIMESTAMP WITH TIME ZONE -contre-
  • TIMESTAMP WITHOUT TIME ZONE

disponible dans le SO post Ignorer complètement les fuseaux horaires dans Rails et PostgreSQL.

Ce que je voudrais savoir, c'est: existe-t-il des cas d'utilisation valides pour utiliser réellement TIMESTAMP WITHOUT TIME ZONE ou doit-il être considéré comme un anti-modèle?

45
Marcus Junius Brutus

Cela est indiqué dans beaucoup d'endroits, mais je pense qu'il vaut la peine de mentionner toujours quand on compare le timestamp with time zone avec timestamp without time zone types: le timestamp WITH time zone ne stocke pas les informations fuseau horaire avec l'horodatage . Ce qu'il fait est de stocker toutes les données dans le fuseau horaire UTC, comme indiqué dans les documents :

Pour l'horodatage avec fuseau horaire, la valeur stockée en interne est toujours en UTC (Universal Coordinated Time, traditionnellement connue sous le nom de Greenwich Mean Time, GMT). Une valeur d'entrée qui a un fuseau horaire explicite spécifié est convertie en UTC en utilisant le décalage approprié pour ce fuseau horaire. Si aucun fuseau horaire n'est indiqué dans la chaîne d'entrée, il est supposé être dans le fuseau horaire indiqué par le paramètre TimeZone du système et est converti en UTC en utilisant le décalage pour le fuseau horaire.

Il est considéré comme valide pour certains d'utiliser timestamp WITHOUT time zone dans les situations où (1) tout est dans le même fuseau horaire ou (2) la couche application gère le fuseau horaire et stocke simplement tout dans un certain fuseau horaire (généralement UTC). Mais il est également considéré comme un anti-modèle, simple parce que la bonne solution pour (1) est de configurer le paramètre TimeZone au fuseau horaire donné pour le système et (2) est déjà résolu, car PostgreSQL stocke déjà tout sur le même fuseau horaire (UTC).

Maintenant, avec ces deux vers le bas, je ne peux avoir qu'une seule bonne raison d'utiliser timestamp WITHOUT time zone. C'est à ce moment que vous souhaitez stocker des événements à l'avenir et qu'une sorte d'alerte doit être déclenchée lorsque nous sommes arrivés à ce moment-là. Cela pourrait être bon pour timestamp WITH time zone si et seulement si les règles définies par les lois régionales sur le fuseau horaire n'ont jamais changé. La règle la plus courante qui change concerne l'adoption ou non de l'heure d'été (DST).

Par exemple, imaginez que vous êtes, disons, 2013-06-15 (pas encore en DST) planifiez un événement à 2013-01-15 10:00 (qui serait déjà en DST) et à 2013-06-15 votre région a été désignée pour adopter l'heure d'été; mais, quelque temps après, le gouvernement a changé la règle et dit que votre région n'utilisera plus l'heure d'été, et soudain, votre heure prévue devient 2013-01-15 11:00 (au lieu de 10:00), que si vous utilisez timestamp WITH time zone, et maintenez vos configurations TZ à jour. Bien sûr, vous pouvez également remarquer qu'il est possible de traiter de tels cas également avec le fuseau horaire, si vous gardez une trace des changements de règles dans les régions/fuseaux horaires de votre intérêt et mettez à jour les enregistrements concernés.

Il convient de mentionner que certaines régions changent souvent ces règles (comme au Brésil, certains États - pas tout le pays - changent souvent), mais dans la plupart des cas, cela le change très tôt, de sorte que vos utilisateurs ne seraient affectés que par des événements programmés très loin de l'heure actuelle.

Cela dit, je n'ai qu'une autre suggestion. Si vous avez des utilisateurs, des journaux ou quoi que ce soit sur différents fuseaux horaires, stockez le fuseau horaire dont ils proviennent quelque part et choisissez et utilisez timestamp with time zone. De cette façon, vous pouvez (1) croiser des événements qui se produisent plus près les uns des autres pour différentes sources (indépendamment de leurs fuseaux horaires) et (2) afficher l'heure d'origine (l'heure de l'horloge) à laquelle l'événement s'est produit.

36
MatheusOl

Oui. Il existe des cas d'utilisation pour TIMESTAMP WITHOUT TIME ZONE.

  • Dans les applications professionnelles courantes, ce type ne serait utilisé que pour:
    • Prise de rendez-vous futurs
    • Représentant la même heure dans différents fuseaux horaires, comme midi le 23 à Tokyo et à Paris (deux moments différents à des heures d'intervalle, même heure)
  • Pour suivre des moments, des points spécifiques sur la chronologie, utilisez toujours TIMESTAMP WITH TIME ZONE, pas WITHOUT.

TIMESTAMP WITHOUT TIME ZONE les valeurs sont pas un point sur la chronologie, pas des moments réels. Ils représentent une idée approximative de potentiel moments, points possibles sur la chronologie sur une plage d'environ 26-27 heures (la plage de fuseaux horaires à travers le monde). Ils n'ont aucune signification réelle jusqu'à ce que vous appliquiez un fuseau horaire ou offset-from-UTC .

Ex: Noël

Par exemple, disons que vous devez enregistrer le début des vacances/jours saints.

Table: holiday_

Column: year_         Type: SMALLINT
Column: description_  Type: VARCHAR
Column: start_        Type: TIMESTAMP WITHOUT TIME ZONE

Pour enregistrer le fait que Noël commence après minuit le 25 décembre de cette année, nous devons dire 2016-12-25 00:00:00 sans aucun fuseau horaire. Tôt dans la journée du Père Noël, il visite Auckland NZ juste après minuit, car il s'agit de l'une des premières minuit du monde. Puis il se dirige vers l'ouest, à minuit suivant, atteignant bientôt les Philippines. Ensuite, les rennes se dirigent vers l'ouest, atteignant l'Inde à minuit, ce qui se produit plusieurs heures après minuit à Auckland. Il est encore beaucoup plus tard à minuit à Paris FR, et encore plus tard à minuit à Montréal CA. Toutes ces visites du Père Noël ont lieu à différents moments sont du temps , mais toutes se sont produites peu après minuit, selon le minuit de chaque localité.

Donc, l'enregistrement 2016-12-25 00:00:00 sans aucun fuseau horaire car le début de Noël est informatif et légitime, mais seulement vaguement. Jusqu'à ce que vous disiez "Noël à Auckland" ou "Noël à Montréal", nous n'avons pas de moment précis. Si vous enregistrez le moment réel à chaque atterrissage du traîneau, vous utiliserez TIMESTAMP WITH TIME ZONE plutôt que le type WITHOUT.

Semblable à Noël, c'est le réveillon du Nouvel An. Quand le Times Square Ball tombe à New York , les gens de Seattle refroidissent toujours leur champagne et préparent leur klaxons . Pourtant, nous enregistrerions le idée du moment du Nouvel An comme 2017-01-01 00:00:00 dans un TIMESTAMP WITHOUT TIME ZONE. En revanche, si nous voulons enregistrer quand le ballon est tombé à New York, ou quand les gens de Seattle se sont fait exploser la corne, nous utiliserions plutôt TIMESTAMP WITH TIME ZONE (pas WITHOUT) pour enregistrer ces moments réels, chacun à trois heures d'intervalle.

Ex: quarts de travail

Un autre exemple pourrait être l'enregistrement d'une politique impliquant heure de l'horloge murale sur différents emplacements. Disons que nous avons des usines à Detroit, Düsseldorf et Delhi. Si nous disons que dans les trois usines, le premier quart commence à 6 heures du matin avec une pause déjeuner à 11h30, cela pourrait être enregistré comme TIMESTAMP WITHOUT TIME ZONE. Encore une fois, ces informations sont utiles de manière vague mais n'indiquent pas un moment précis dans le temps jusqu'à ce que nous appliquions un fuseau horaire. Un nouveau jour se lève plus tôt dans l'est. L'usine de Delhi sera donc la première à ouvrir à 6 heures du matin. Quelques heures plus tard, l'usine de Düsseldorf commence ses travaux à 6 heures du matin. Mais l'usine de Détroit n'ouvrira en fait que six heures plus tard, lorsque son heure du matin arrivera.

Comparez cette idée (à savoir quand commence généralement le quart de travail) avec le fait historique de quand chaque ouvrier d'usine a-t-il commencé son quart de travail un jour particulier. L'horloge est un vrai moment, un point réel sur la chronologie. Nous enregistrerions donc cela dans une colonne de type TIMESTAMP WITH TIME ZONE plutôt que le type WITHOUT.

Donc, oui, il existe des cas d'utilisation légitimes pour TIMESTAMP WITHOUT TIME ZONE. Mais d'après mon expérience avec les applications d'entreprise, elles sont relativement rares. Dans les affaires, nous avons tendance à nous soucier des moments réels: quand la facture est-elle arrivée, quand exactement ce contrat entre-t-il en vigueur, à quel moment cette transaction bancaire s'est-elle exécutée. Donc, dans de telles situations courantes, nous voulons que le TIMESTAMP WITH TIME ZONE type.

Pour plus de discussion, voir ma réponse à la question similaire, Dois-je stocker les horodatages UTC ou l'heure locale pour les quarts

Postgres

Notez que Postgres spécifiquement jamais enregistre les informations de fuseau horaire spécifiées lors de l'insertion d'un horodatage.

  • TIMESTAMP WITH TIME ZONE
    • Tout fuseau horaire ou décalage spécifié inclus avec les données d'entrée est utilisé pour ajuster la valeur sur UTC et stocké. Les informations de zone/décalage transmises sont ensuite supprimées. Penser à TIMESTAMP WITH TIME ZONE comme TIMESTAMP WITH RESPECT FOR TIME ZONE.
    • Une entrée de midi le 7 mars de cette année en Inde verra son heure ajustée à UTC en soustrayant cinq heures et demie: 6h30.
  • TIMESTAMP WITHOUT TIME ZONE
    • Tout fuseau horaire ou décalage spécifié inclus avec les données d'entrée est entièrement ignoré.
    • Une entrée de 12h00 le 7 mars de cette année en Inde est enregistrée à 12h00 le 7 mars de cette année sans aucun ajustement.

Le standard SQL touche à peine aux problèmes de types de données date-heure et de comportement. La base de données varie donc largement dans la gestion de la date et de l'heure.

23
Basil Bourque

J'aimerais ajouter un autre point de vue à cela, ce qui va à l'encontre de la plupart des écrits des autres réponses. À mon avis timestamp with time zone a très peu de cas d'utilisation valides et timestamp without time zone devrait en général être préféré.

Tout d'abord, vous devez comprendre le modèle "UTC partout", qui est généralement recommandé pour toutes les applications qui n'ont pas d'exigences très particulières. Cela signifie simplement que votre application doit représenter tous ses horodatages en UTC, partout et à tout moment. Bien sûr, vous afficherez la date/heure locale aux utilisateurs, mais l'idée est de les convertir au bord même de votre programme, lors du rendu de la vue. C'est le bon endroit pour combiner l'horodatage UTC (que vous avez peut-être chargé à partir d'une base de données) et le fuseau horaire de l'utilisateur (qui peut provenir du navigateur) dans un horodatage local.

Si vous suivez ce modèle, alors timestamp with time zone est un anti-motif. Tout ce que ce type fait, c'est que PostgreSQL effectue des conversions de fuseau horaire lors de la lecture et de l'écriture d'horodatages, en fonction de votre variable de session PostgreSQL TimeZone. Au lieu de traiter des fuseaux horaires aux extrémités de votre application, vous les avez introduits en son cœur, dans la communication même avec votre base de données. Vous devez prendre soin de toujours avoir PostgreSQL TimeZone correctement configuré à tout moment, ajoutant un autre point inutile d'échec et de confusion.

Et pour quoi? Si vous suivez le modèle UTC partout, votre application n'a de toute façon que des horodatages UTC; alors pourquoi demander à votre base de données d'effectuer des conversions de fuseau horaire sur eux? Vous pouvez simplement les stocker dans un timestamp without time zone colonne, et traitez-la comme si c'était toujours UTC. Pas de conversions, pas de fuseaux horaires, pas de complications.

14
Shay Rojansky

L'horodatage date n'inclut pas non plus les informations de fuseau horaire, mais beaucoup de gens l'utilisent.

Bien sûr, cela en soi n'est pas une réponse.

Il est valide d'utiliser timestamp et date pour tous les horodatages et les dates qui sont toujours dans le même fuseau horaire, ou qui sont stockés par rapport à un fuseau horaire connu.

Si le fuseau horaire est toujours le même ou implicite, il est plus anti-modèle de le stocker que de ne pas le stocker (informations redondantes).

Les horodatages peuvent également être utilisés pour stocker des informations techniques telles que celles utilisées dans les journaux d'application ou pour les mesures de performances. Dans ce cas, le fuseau horaire peut également être sans importance.


Inversement, si vous concevez ou travaillez sur un système distribué ou dans tout système où des parties du système seront réparties sur différents fuseaux horaires, il peut être considéré comme un anti-modèle de ne pas utiliser timestamp with timezone, bien que certains systèmes puissent être conçus pour fonctionner dans un seul fuseau horaire, par exemple UTC. Dans ce cas, la logique du fuseau horaire peut être poussée dans la couche application - mais je considérerais cela comme un anti-modèle, oui.

3
Colin 't Hart

Il peut sembler tentant de stocker et de traiter les dates/heures en heure locale si votre application est limitée à un seul fuseau horaire, mais je pense que c'est une erreur.

Lors du retour de l'heure d'été à l'heure d'hiver, une heure locale est répétée (en supposant que la différence est d'une heure). Là où j'habite, cela se produit généralement vers 2 heures du matin, donc l'heure locale fonctionne à 01h58, 01h59, 01h00 et n'avance qu'à 02h00 à la fin de l'heure répétée.

Si vous essayez de classer les événements en fonction de l'heure locale, cela signifie que les événements de deux heures distinctes sont mélangés et n'apparaissent pas dans l'ordre dans lequel ils se sont réellement produits.

Par comparaison, UTC n'a pas ce problème et commande proprement. Ainsi, même lorsque vous travaillez avec un seul fuseau horaire, vous souhaitez que la base de données stocke et traite les heures en UTC et les convertisse en/à partir de l'heure locale pour l'entrée/l'affichage. Il s'agit du comportement de TIMESTAMP WITH TIME ZONE.

2
Steve Fosdick