Obtenir le fuseau horaire de DateTime

103

Le .Net DateTime contient-il des informations sur le fuseau horaire où il a été créé?

J'ai une bibliothèque analysant DateTime à partir d'un format qui a "+ zz" à la fin, et pendant qu'elle analyse correctement et ajuste une heure locale, j'ai besoin d'obtenir ce que le fuseau horaire spécifique était de l'objet DateTime.

Est-ce possible? Tout ce que je peux voir, c'est DateTime.Kind, qui spécifie si l'heure est locale ou UTC.

dbkk
la source
Voir les notes sur la documentation DateTime.Parse pour la gestion des fuseaux horaires et des DateTimeStyles. Mais non, ce que vous voulez n'est pas vraiment possible.
yoyo

Réponses:

136

DateTime lui-même ne contient aucune information de fuseau horaire réel. Il peut savoir si c'est UTC ou local, mais pas ce que signifie vraiment local.

DateTimeOffset est un peu mieux - c'est essentiellement une heure UTC et un décalage. Cependant, ce n'est toujours pas vraiment suffisant pour déterminer le fuseau horaire, car de nombreux fuseaux horaires différents peuvent avoir le même décalage à tout moment. Cela semble cependant être assez bon pour vous, car tout ce que vous avez à faire pour analyser la date / heure est le décalage.

La prise en charge des fuseaux horaires à partir de .NET 3.5 est bien meilleure qu'elle ne l'était, mais j'aimerais vraiment voir un "ZonedDateTime" standard ou quelque chose comme ça - une heure UTC et un fuseau horaire réel. Il est facile de créer le vôtre, mais ce serait bien de le voir dans les bibliothèques standard.

EDIT: Près de quatre ans plus tard, je suggère maintenant d'utiliser Noda Time qui a un ensemble plutôt plus riche de types de date / heure. Je suis cependant partial, en tant qu'auteur principal de Noda Time :)

Jon Skeet
la source
2
Le projet PublicDomain sur CodePlex le fait pour vous.
Cheeso
Une énumération TimeZone dans la BCL serait bien si les fuseaux horaires mondiaux sont statiques et ne changent pas.
Jeff LaFay
1
@jlafay: Cependant, ils changent - plus de fuseaux horaires ont été ajoutés à Windows l'année dernière, par exemple.
Jon Skeet
Ce projet n'est plus maintenu par l'auteur; publicdomain.codeplex.com Il semble que celui-ci pourrait peut-être aider, selon l'utilisation, il faut le configurer avant de l'utiliser; timezone.codeplex.com
AnneTheAgile
3
@AnneTheAgile: Personnellement, je recommanderais d'utiliser ma propre bibliothèque Noda Time, bien sûr :)
Jon Skeet
36

Non.

Un développeur est responsable du suivi des informations de fuseau horaire associées à une valeur DateTime via un mécanisme externe.

Une citation d'un excellent article ici . Une lecture incontournable pour chaque développeur .Net.

Mon conseil est donc d'écrire une petite classe de wrapper qui répond à vos besoins.

Gerrie Schenck
la source
2

Vous pouvez utiliser la classe TimeZoneInfo

La classe TimeZone reconnaît le fuseau horaire local et peut convertir les heures entre le temps universel coordonné (UTC) et l'heure locale. Un objet TimeZoneInfo peut représenter n'importe quel fuseau horaire et les méthodes de la classe TimeZoneInfo peuvent être utilisées pour convertir l'heure dans un fuseau horaire en heure correspondante dans n'importe quel autre fuseau horaire. Les membres de la classe TimeZoneInfo prennent en charge les opérations suivantes:

  1. Récupération d'un fuseau horaire déjà défini par le système d'exploitation.

  2. Énumération des fuseaux horaires disponibles sur un système.

  3. Conversion des heures entre différents fuseaux horaires.

  4. Création d'un nouveau fuseau horaire qui n'est pas déjà défini par le système d'exploitation.

    Sérialisation d'un fuseau horaire pour une récupération ultérieure.

Shekhar
la source
1
... mais, étant donné un DateTime, il n'y a toujours pas de moyen d'utiliser TimeZoneInfo pour déterminer la TimeZone de DateTime, à ma connaissance.
Remi Despres-Smyth
@ RemiDespres-Smyth Je viens de stocker TimeZoneInfo avec DateTime dans 1 classe.
Konrad
0

En règle générale, la pratique consiste à transmettre des données en tant que DateTime avec un "fuseau horaire" UTC, puis à transmettre un objet TimeZoneInfo et lorsque vous êtes prêt à afficher les données, vous utilisez l'objet TimeZoneInfo pour convertir le DateTime UTC.

L'autre option consiste à définir le DateTime avec le fuseau horaire actuel, puis à s'assurer que le "fuseau horaire" est inconnu pour l'objet DateTime, puis à s'assurer que le DateTime est à nouveau passé avec un TimeZoneInfo qui indique le fuseau horaire du DateTime passé.

Comme d'autres l'ont indiqué ici, ce serait bien que Microsoft prenne le dessus et crée un bel objet pour tout faire, mais pour l'instant, vous devez gérer deux objets.

Rob
la source
0

DateTime ne connaît pas son décalage de fuseau horaire. Il n'y a pas de méthode intégrée pour renvoyer le décalage ou le nom du fuseau horaire (par exemple EAT, CEST, EST, etc.).

Comme suggéré par d'autres, vous pouvez convertir votre date en UTC:

DateTime localtime = new DateTime.Now;
var utctime = localtime.ToUniversalTime();

puis calculez uniquement la différence:

TimeSpan difference = localtime - utctime;

Vous pouvez également convertir une heure en une autre en utilisant DateTimeOffset:

DateTimeOffset targetTime = DateTimeOffset.Now.ToOffset(new TimeSpan(5, 30, 0));

Mais c'est une sorte de compression avec perte - le décalage seul ne peut pas vous dire de quel fuseau horaire il s'agit car deux pays différents peuvent être dans des fuseaux horaires différents et avoir la même heure seulement pendant une partie de l'année (par exemple, l'Afrique du Sud et l'Europe). Sachez également que l'heure d'été peut être introduite à des dates différentes (HNE vs HEC - une différence de 3 semaines).

Vous pouvez obtenir le nom de votre fuseau horaire système local à l'aide de la classe TimeZoneInfo:

TimeZoneInfo localZone = TimeZoneInfo.Local;
localZone.IsDaylightSavingTime(localtime) ? localZone.DaylightName : localZone.StandardName

Je suis d'accord avec Gerrie Schenck, veuillez lire l'article qu'il a suggéré.

henryalligator
la source