DateTimeOffset
est une représentation du temps instantané (également appelé temps absolu ). Par cela, je veux dire un moment dans le temps qui est universel pour tout le monde (sans compter les secondes intercalaires ou les effets relativistes de la dilatation du temps ). Une autre façon de représenter le temps instantané est avec un DateTime
où .Kind
est DateTimeKind.Utc
.
Ceci est distinct du temps du calendrier (également connu sous le nom de temps civil ), qui est une position sur le calendrier de quelqu'un, et il existe de nombreux calendriers différents dans le monde entier. Nous appelons ces calendriers des fuseaux horaires . L'heure du calendrier est représentée par un DateTime
où .Kind
est DateTimeKind.Unspecified
, ou DateTimeKind.Local
. Et .Local
n'a de sens que dans les scénarios où vous avez une compréhension implicite de l'emplacement de l'ordinateur qui utilise le résultat. (Par exemple, le poste de travail d'un utilisateur)
Alors, pourquoi DateTimeOffset
au lieu d'un UTC DateTime
? Tout est question de perspective. Prenons une analogie - nous prétendons être des photographes.
Imaginez que vous vous tenez sur une chronologie de calendrier, pointant une caméra vers une personne sur la chronologie instantanée disposée devant vous. Vous alignez votre caméra selon les règles de votre fuseau horaire - qui changent périodiquement en raison de l'heure d'été ou en raison d'autres modifications de la définition légale de votre fuseau horaire. (Vous n'avez pas une main ferme, donc votre appareil photo est fragile.)
La personne debout sur la photo verrait l'angle sous lequel votre appareil photo est venu. Si d'autres prenaient des photos, elles pourraient prendre des angles différents. C'est ce que représente la Offset
partie du DateTimeOffset
.
Donc, si vous étiquetez votre appareil photo "heure de l'Est", parfois vous pointez à partir de -5, et parfois vous pointez à partir de -4. Il y a des caméras partout dans le monde, toutes étiquetées des choses différentes, et toutes pointant vers la même chronologie instantanée sous différents angles. Certains d'entre eux sont juste à côté (ou au-dessus) les uns des autres, il ne suffit donc pas de connaître le décalage pour déterminer le fuseau horaire auquel l'heure est liée.
Et qu'en est-il de l'UTC? Eh bien, c'est la seule caméra qui est garantie d'avoir une main ferme. C'est sur un trépied, fermement ancré dans le sol. Ça ne va nulle part. Nous appelons son angle de perspective le décalage nul.
Alors - que nous dit cette analogie? Il fournit des directives intuitives-
Si vous représentez le temps par rapport à un endroit en particulier, représentez-le en temps calendaire avec a DateTime
. Assurez-vous simplement de ne jamais confondre un calendrier avec un autre. Unspecified
devrait être votre hypothèse. Local
est seulement utile venant de DateTime.Now
. Par exemple, je pourrais l'obtenir DateTime.Now
et l'enregistrer dans une base de données - mais quand je le récupère, je dois supposer que c'est le cas Unspecified
. Je ne peux pas compter sur le fait que mon calendrier local est le même que celui à l'origine.
Si vous devez toujours être certain du moment, assurez-vous de représenter le temps instantané. Utilisez DateTimeOffset
pour l'appliquer, ou utilisez UTC DateTime
par convention.
Si vous avez besoin de suivre un moment instantané, mais que vous voulez également savoir "À quelle heure l'utilisateur pensait-il qu'il était sur son calendrier local?" - alors vous devez utiliser un DateTimeOffset
. C'est très important pour les systèmes de chronométrage, par exemple - à la fois pour des questions techniques et juridiques.
Si vous devez modifier un enregistrement antérieur DateTimeOffset
, vous n'avez pas suffisamment d'informations dans le décalage seul pour vous assurer que le nouveau décalage est toujours pertinent pour l'utilisateur. Vous devez également stocker un identifiant de fuseau horaire (pensez - j'ai besoin du nom de cette caméra pour pouvoir prendre une nouvelle photo même si la position a changé).
Il convient également de noter que Noda Time a une représentation appelée ZonedDateTime
à cet effet, tandis que la bibliothèque de classes de base .Net n'a rien de similaire. Vous devez stocker à la fois DateTimeOffset
une TimeZoneInfo.Id
valeur et une valeur.
Parfois, vous souhaiterez représenter une heure de calendrier qui est locale à "celui qui la regarde". Par exemple, lors de la définition de ce que signifie aujourd'hui . Aujourd'hui est toujours de minuit à minuit, mais ceux-ci représentent un nombre presque infini de plages qui se chevauchent sur la chronologie instantanée. (Dans la pratique, nous avons un nombre fini de fuseaux horaires, mais vous pouvez exprimer des décalages jusqu'à la graduation). Donc, dans ces situations, assurez-vous de comprendre comment limiter le "qui demande?" question vers le bas à un seul fuseau horaire, ou de les traduire en temps instantané, le cas échéant.
Voici quelques autres petits détails à DateTimeOffset
ce sujet pour sauvegarder cette analogie, et quelques conseils pour la garder droite:
Si vous comparez deux DateTimeOffset
valeurs, elles sont d'abord normalisées à un décalage nul avant de les comparer. En d'autres termes, 2012-01-01T00:00:00+00:00
et se 2012-01-01T02:00:00+02:00
réfèrent au même moment instantané, et sont donc équivalents.
Si vous effectuez un test unitaire et devez être certain du décalage, testez à la fois la DateTimeOffset
valeur et la .Offset
propriété séparément.
Il existe une conversion implicite unidirectionnelle intégrée au framework .Net qui vous permet de passer un DateTime
dans n'importe quel DateTimeOffset
paramètre ou variable. Ce faisant, les .Kind
questions . Si vous passez un type UTC, il se poursuivra avec un décalage nul, mais si vous passez l'un .Local
ou l' autre .Unspecified
, il supposera être local . Le cadre dit essentiellement: "Eh bien, vous m'avez demandé de convertir le temps du calendrier en temps instantané, mais je n'ai aucune idée d'où cela vient, donc je vais simplement utiliser le calendrier local." C'est un énorme problème si vous chargez un fichier non spécifié DateTime
sur un ordinateur avec un fuseau horaire différent. (À mon humble avis - cela devrait lever une exception - mais ce n'est pas le cas.)
Prise sans vergogne:
Beaucoup de gens ont partagé avec moi qu'ils trouvent cette analogie extrêmement précieuse, donc je l'ai incluse dans mon cours Pluralsight, Fondamentaux de la date et de l'heure . Vous trouverez une procédure pas à pas de l'analogie de la caméra dans le deuxième module, "Context Matters", dans le clip intitulé "Calendar Time vs. Instantaneous Time".