321 votes

Convertir l’heure GMT/UTC en heure locale

Nous développons actuellement une application en C# pour un client du service web. Ce sera exécuté sur Windows XP PC.

L'un des champs retournés par le service web est un champ DateTime. Le serveur renvoie un champ en format GMT c'est à dire avec un "Z" à la fin.

Cependant, nous avons constaté que les .NET semble faire une sorte de conversion implicite et le temps est toujours de 12 heures.

L'exemple de code suivant résout ce dans une certaine mesure, que les 12 heures de différence a disparu, mais il ne fait aucune provision pour NZ heure d'été.

CultureInfo ci = new CultureInfo("en-NZ");
string date = "Web service date".ToString("R", ci);
DateTime convertedDate = DateTime.Parse(date);            

Conformément à cette date site:

UTC/GMT Offset

Fuseau horaire: UTC/GMT +12 heures
Heure d'été: +1 heure
Actuel décalage horaire: UTC/GMT +13 heures

Comment pouvons-nous régler pour l'heure supplémentaire? Cela peut être fait par programmation ou de configuration sur le PC?

390voto

Drew Noakes Points 69288

Pour des chaînes telles que 2012-09-19 01:27:30.000, DateTime.Parse ne peut pas dire à quelle heure de la zone de la date et de l'heure.

DateTime a un Type de propriété, ce qui peut avoir l'une des trois options de fuseau horaire:

  • Non spécifié
  • Local
  • Utc

REMARQUE Si vous êtes désireux de représenter une date/heure autre que l'UTC ou de votre fuseau horaire local, puis vous devez utiliser DateTimeOffset.


Donc, pour le code dans votre question:

DateTime convertedDate = DateTime.Parse(dateStr);

var kind = convertedDate.Kind; // will equal DateTimeKind.Unspecified

Vous dites que vous savez quel genre il est, pour ainsi dire.

DateTime convertedDate = DateTime.SpecifyKind(
    DateTime.Parse(dateStr),
    DateTimeKind.Utc);

var kind = convertedDate.Kind; // will equal DateTimeKind.Utc

Maintenant, une fois que le système connaît son heure UTC, vous pouvez les appeler ToLocalTime:

DateTime dt = convertedDate.ToLocalTime();

Cela vous donnera le résultat que vous désirez.

125voto

Daniel Ballinger Points 4883

Je voudrais regarder dans à l’aide de la classe System.TimeZoneInfo, si vous êtes dans .NET 3.5. Voir http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx. Cela devrait prendre en compte les changements d’économies de lumière du jour correctement.

61voto

Dana Points 1911
TimeZone.CurrentTimeZone.ToLocalTime(date);

16voto

David Points 1001

Je sais que c'est une vieille question, mais j'ai couru dans une situation similaire, et je voulais partager ce que j'avais trouvé pour les futurs chercheurs, éventuellement, y compris moi-même :).

DateTime.Parse() peut être difficile-voir ici par exemple.

Si l' DateTime est à venir à partir d'un service Web ou d'une autre source avec un format connu, vous pourriez envisager quelque chose comme

DateTime.ParseExact(dateString, 
                   "MM/dd/yyyy HH:mm:ss", 
                   CultureInfo.InvariantCulture, 
                   DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal)

ou, encore mieux,

DateTime.TryParseExact(...)

L' AssumeUniversal drapeau indique à l'analyseur que la date/heure est déjà UTC; l' AdjustToUniversal indicateur permet de ne pas convertir le résultat en "local" de temps, il va essayer de le faire par défaut. (Personnellement, j'essaie de traiter exclusivement avec l'UTC dans l'entreprise / l'application / service de couche(s) de toute façon. Mais en contournant la conversion en heure locale aussi de la vitesse, -- par 50% ou plus dans mes tests, voir ci-dessous).

Voici ce que nous faisions avant:

DateTime.Parse(dateString, new CultureInfo("en-US"))

Nous avions dressé le portrait de la app et a constaté que le type DateTime.Analyser ce qui représentait un important pourcentage d'utilisation du PROCESSEUR. (Soit dit en passant, l' CultureInfo constructeur était pas un contributeur important à l'utilisation de l'UC.)

J'ai donc mis en place une application console pour analyser une chaîne de date/heure 10000 fois dans une variété de façons. Bas de ligne:
Parse() 10 sec
ParseExact() (conversion au local) de 20 à 45 ms
ParseExact() (pas de conversion de locaux) 10-15 ms
... et oui, les résultats de l' Parse() sont en secondes, alors que les autres sont en millisecondes.

15voto

Mark T Points 1276

Je voudrais juste ajouter une note générale de prudence.

Si tout ce que vous faites est d'arriver à l'heure actuelle de l'horloge de l'ordinateur pour mettre une date/heure sur l'afficheur ou un rapport, alors tout est bien. Mais si vous êtes enregistrement de la date et de l'heure de référence pour plus tard ou le calcul de la date/temps, méfiez-vous!

Disons que vous déterminer un navire de croisière est arrivé à Honolulu le 20 Décembre 2007 à 15:00 UTC. Et vous voulez savoir ce que l'heure locale qui a été.
1. Il y a probablement au moins trois "gens du pays" concernés. Local peut signifier Honolulu, ou il peut signifier emplacement de votre ordinateur, ou il peut signifier l'emplacement où se trouve votre client.
2. Si vous utilisez les fonctions intégrées pour faire la conversion, il sera probablement tort. C'est parce que l'heure d'été est (probablement) actuellement en vigueur sur votre ordinateur, mais n'était PAS en vigueur en décembre. Mais Windows ne le sait pas... il a est un indicateur pour déterminer si l'heure d'été est en vigueur actuellement. Et si elle est actuellement en vigueur, alors il se fera un plaisir d'ajouter une heure, même pour une date en décembre.
3. L'heure d'été est mis en œuvre différemment (ou pas du tout) dans les différentes subdivisions politiques. Ne pensez pas que juste parce que votre pays modifications à une date précise, que d'autres pays aussi.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X