Comment fonctionne la conversion en UTC à partir du format DateTime
standard?
Plus précisément, si je crée un object DateTime
dans un fuseau horaire, puis passe à un autre fuseau horaire et exécute ToUniversalTime()
, comment sait-il que la conversion a été effectuée correctement et que l’heure est toujours correctement représentée?
Il n’y a pas de fuseau horaire implicite attaché à un object DateTime
. Si vous exécutez ToUniversalTime()
dessus, il utilise le fuseau horaire du contexte dans lequel le code est exécuté.
Par exemple, si je crée un DateTime
partir de l’époque du 1/1/1970, cela me donne le même object DateTime
, peu importe où je suis dans le monde.
Si ToUniversalTime()
quand ToUniversalTime()
le code dans Greenwich, je reçois le même temps. Si je le fais pendant que je vis à Vancouver, je reçois un object DateTime
décalé de -8 heures.
C’est pourquoi il est important de stocker les informations relatives à l’heure dans votre firebase database sous forme de temps UTC lorsque vous devez effectuer une conversion ou une localisation de date. Déterminez si votre base de code a été déplacée vers une installation de serveur dans un autre fuseau horaire;)
Edit: note de la réponse de Joel – Les objects DateTime
par défaut sont tapés comme DateTimeKind.Local
. Si vous parsingz une date et la définissez comme DateTimeKind.Utc
, ToUniversalTime()
aucune conversion.
Et voici un article sur le “Codage des meilleures pratiques avec la date et l’ heure ” , et un article sur la conversion des date et heure avec .Net .
Tout d’abord, il vérifie que le Kind
de DateTime
est déjà connu pour être UTC. Si oui, il renvoie la même valeur.
Sinon, il est supposé être une heure locale – locale à l’ordinateur sur lequel il s’exécute, et en particulier dans le fuseau horaire utilisé par l’ordinateur lors de l’initialisation de certaines propriétés privées. Cela signifie que si vous modifiez le fuseau horaire après le démarrage de votre application, il y a de fortes chances que vous utilisiez toujours l’ancien.
Le fuseau horaire contient suffisamment d’informations pour convertir une heure locale en heure UTC ou vice versa, bien qu’il y ait des moments ambigus ou non valides. (Il existe des heures locales qui se produisent deux fois et des heures locales qui ne se produisent jamais en raison de l’heure d’été.) Les règles de traitement de ces cas sont spécifiées dans la documentation :
Si la valeur de l’instance de date et d’heure est une heure ambiguë, cette méthode suppose qu’il s’agit d’une heure standard. (Une heure ambiguë peut correspondre à une heure standard ou à une heure d’été dans le fuseau horaire local) Si la valeur de l’instance de date et d’heure est une heure non valide, cette méthode soustrait simplement l’heure locale du fuseau horaire local. Décalage UTC pour renvoyer UTC. (Une heure non valide est celle qui n’existe pas en raison de l’application des règles d’ajustement de l’heure d’été.)
La valeur renvoyée aura une Kind
de DateTimeKind.Utc
, donc si vous appelez ToUniveralTime
, il n’appliquera plus le décalage. (Ceci est une grande amélioration par rapport à .NET 1.1!)
Si vous voulez un fuseau horaire non local, vous devez utiliser TimeZoneInfo
qui a été introduit dans .NET 3.5 (il existe des solutions de piratage pour les versions antérieures, mais elles ne sont pas bonnes). Pour représenter un instant, vous devriez envisager d’utiliser DateTimeOffset
qui a été introduit dans .NET 2.0SP1, .NET3.0SP1 et .NET 3.5. Toutefois, aucun fuseau horaire ne lui est associé – juste un décalage par rapport à UTC. Cela signifie que vous ne savez pas quelle heure locale sera une heure plus tard, par exemple – les règles DST peuvent varier entre les fuseaux horaires qui utilisent le même décalage pour cet instant particulier. TimeZoneInfo
est conçu pour prendre en compte les règles historiques et futures, par opposition à TimeZone
qui est quelque peu simpliste.
Fondamentalement, le support dans .NET 3.5 est bien meilleur qu’il ne l’était, mais laisse toujours à désirer pour l’arithmétique du calendrier. Quelqu’un a-t-il envie de porter Joda Time sur .NET? 😉
Ce que @womp a dit , avec en plus qu’il vérifie la propriété Kind de DateTime pour voir s’il peut déjà s’agir d’une date UTC.
DateTime.ToUniversalTime supprime le décalage du fuseau horaire du fuseau horaire local pour normaliser un DateTime sur UTC. Si vous utilisez ensuite DateTime.ToLocalTime sur la valeur normalisée dans un autre fuseau horaire, le décalage du fuseau horaire de ce fuseau horaire sera ajouté à la valeur normalisée pour une représentation correcte dans ce fuseau horaire.