Stockage de DateTime (UTC) ou stockage de DateTimeOffset

95

J'ai généralement un "intercepteur" qui, juste avant de lire / écrire de / vers la base de données, effectue la conversion DateTime (de UTC en heure locale et de l'heure locale en UTC), donc je peux utiliser DateTime.Now(dérivations et comparaisons) dans tout le système sans me soucier sur les fuseaux horaires.

En ce qui concerne la sérialisation et le déplacement des données entre les ordinateurs, il n'y a pas besoin de s'inquiéter, car le datetime est toujours UTC.

Dois-je continuer à stocker mes dates (SQL 2008 - datetime) au format UTC ou devrais-je plutôt les stocker en utilisant DateTimeOffset (SQL 2008 - datetimeoffset)?

Les dates UTC dans la base de données (type datetime) fonctionnent et sont connues depuis si longtemps, pourquoi les changer? Quels sont les avantages?

J'ai déjà examiné des articles comme celui-ci , mais je ne suis pas convaincu à 100%. Des pensées?

Frederico
la source
Question connexe: stackoverflow.com/questions/2532729/…
Oded le
1
Voir aussi: DateTime vs DateTimeOffset - écrit pour .Net, mais s'applique également conceptuellement à SQL.
Matt Johnson-Pint

Réponses:

131

Il y a une énorme différence, où vous ne pouvez pas utiliser UTC seul.

  • Si vous avez un scénario comme celui-ci

    • Un serveur et plusieurs clients (tous géographiquement dans des fuseaux horaires différents )
    • Les clients créent des données avec des informations datetime
    • Les clients stockent tout sur le serveur central
  • Ensuite:

    • datetimeoffset stocke l'heure locale du client et le décalage ALSO par rapport à l'heure UTC
    • tous les clients connaissent l'heure UTC de toutes les données et également une heure locale à l'endroit d'où proviennent les informations
  • Mais:

    • L'heure de date UTC stocke uniquement la date et l'heure UTC , vous n'avez donc pas d'informations sur l'heure locale à l'emplacement du client d'où proviennent les données
    • Les autres clients ne connaissent pas l'heure locale du lieu, d'où proviennent les informations datetime
    • Les autres clients ne peuvent calculer leur heure locale qu'à partir de la base de données (en utilisant l'heure UTC) et non l'heure locale du client, d'où proviennent les données

Un exemple simple est le système de réservation de billets d'avion ... Le billet d'avion doit contenir 2 heures: - l'heure de «décollage» (dans le fuseau horaire de la ville «De») - l'heure «d'atterrissage» (dans le fuseau horaire de la ville de «destination»)

Marcel Toth
la source
2
C'est la meilleure explication que j'ai lue sur le moment où cela serait approprié, et j'ai beaucoup lu Pour nous, à partir de là, cela ne semble pas être le cas. Nous obtenons l'heure en UTC pour nos données externes, et nous connaissons l'emplacement d'une autre source si nécessaire (et cela ne l'a jamais été). Merci d'avoir rendu cela si évident.
Andrew Backer
19
vous avez dit "datetimeoffset stocke l'heure UTC et également le décalage par rapport à l'heure locale du client", mais datetimeoffset stocke l'heure LOCAL + Offset, ou l'heure UTC + offset égale +0.
Serhii Kyslyi
bien que vous puissiez simplement convertir le DTO en DT puisque la base DT est UTC (bien que ce serait une étape supplémentaire pour tous ceux qui utilisent la base de données, et ce n'est sans doute pas plus simple que d'utiliser l'heure UTC seule)
iliketocode
2
On dirait plus que DateTmeOffset stocke "Heure locale et décalage UTC", et non "Heure UTC et décalage UTC". Si vous effectuez un cast en datetime ou utilisez l'une des fonctions datepart, vous obtenez les composants de date et d'heure locaux.
Triynko du
" Tous les clients connaissent l'heure UTC de toutes les données et aussi l'heure locale de l'endroit où les informations proviennent" Bien que le stockage dans le cadre du champ de date ne soit pas normalisé dans ce cas. Quel est le cas d'utilisation - c'est-à-dire pourquoi n'utiliseriez-vous pas UTC et retirez-vous le décalage vers InputLocationId(ou une entité normalisée similaire). Il y aurait des calculs impliqués (bonjour, des exceptions ... en particulier vous, Indiana ), mais c'est toujours un processus déterministe - et ensuite l'équilibre de la logique datetime de l'application est simple.
ruffin le
23

Vous avez tout à fait raison d'utiliser UTC pour toutes les heures historiques (c'est-à-dire que les événements d'enregistrement se sont produits). Il est toujours possible de passer de l'heure UTC à l'heure locale, mais pas toujours l'inverse.

Quand utiliser l'heure locale? Répond a cette question:

Si le gouvernement décide soudainement de modifier l'heure d'été, aimeriez-vous que ces données changent avec elle?

Ne stockez l'heure locale que si la réponse est «oui». Évidemment, ce ne sera que pour les dates futures, et généralement uniquement pour les dates qui affectent les gens d'une manière ou d'une autre.

Pourquoi stocker un fuseau horaire / un décalage?

Premièrement, si vous voulez enregistrer le décalage pour l'utilisateur qui a effectué l'action, vous feriez probablement mieux de le faire, c'est-à-dire, lors de la connexion, enregistrez l'emplacement et le fuseau horaire de cet utilisateur.

Deuxièmement, si vous souhaitez convertir pour l'affichage, vous devez avoir un tableau de toutes les transitions de décalage horaire local pour ce fuseau horaire, il ne suffit pas de connaître le décalage actuel, car si vous affichez une date / heure d'il y a six mois, le décalage sera sois différent.

Ben
la source
4
La conversion de Windows UTC en heure locale prend en compte le changement d'heure d'été pour les dates historiques. Je ne vois pas pourquoi vous voudriez stocker l'heure locale dans ce cas.
Jamiegs
1
@Jamiegs Windows ne connaît historiquement que les "dernières informations historiques" (comme l'indique / noté dans la documentation .NET DateTime). Ce n'est pas complet.
2
bien sûr, vous devez également stocker le lieu de l'événement, sinon vous ne pouvez pas dire à quelle "heure locale" l'événement s'est produit.
keuleJ
20

Un DATETIMEOFFSET vous donne la possibilité de stocker l'heure locale et l'heure UTC dans un seul champ.

Cela permet des rapports très simples et efficaces en heure locale ou UTC sans qu'il soit nécessaire de traiter les données à afficher de quelque manière que ce soit.

Ce sont les deux exigences les plus courantes: l'heure locale pour les rapports locaux et l'heure UTC pour les rapports de groupe.

L'heure locale est stockée dans la partie DATETIME du DATETIMEOFFSET et l'OFFSET d'UTC est stocké dans la partie OFFSET, la conversion est donc simple et, puisqu'elle ne nécessite aucune connaissance du fuseau horaire d'où proviennent les données, tout peut être effectué au niveau de la base de données .

Si vous n'avez pas besoin de temps allant jusqu'à des millisecondes, par exemple juste à quelques minutes ou secondes, vous pouvez utiliser DATETIMEOFFSET (0). Le champ DATETIMEOFFSET ne nécessitera alors que 8 octets de stockage - le même que DATETIME.

Utiliser un DATETIMEOFFSET plutôt qu'un DATETIME UTC donne donc plus de flexibilité, d'efficacité et de simplicité pour le reporting.

PapillonUK
la source
Dommage que le framework d'entité n'ait aucun moyen d'accéder à la date / heure locale d'un champ datetimeoffset, ce qui rend impossible l'interrogation d'une date locale particulière.
Triynko
@Triynko pouvez-vous expliquer ce que vous voulez dire? Exemple?
reidLinden