2010-06-02 18 views
57

J'essaie d'utiliser DateTimeOffset pour transmettre un moment spécifique dans n'importe quel fuseau horaire. Je n'arrive pas à comprendre comment utiliser TimeZoneInfo pour gérer l'heure d'été.Comment utiliser TimeZoneInfo pour obtenir l'heure locale pendant l'heure d'été?

var dt = DateTime.UtcNow; 
Console.WriteLine(dt.ToLocalTime()); 

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero); 
Console.WriteLine(utcOffset.ToOffset(tz.BaseUtcOffset)); 

Ceci affiche:

6/2/2010 4:37:19 PM 
6/2/2010 3:37:19 PM -06:00 

Je suis dans le fuseau horaire central, et nous sommes actuellement en heure d'été. Je suis en train d'obtenir la deuxième ligne à lire:

6/2/2010 4:37:19 PM -05:00 

BaseUtcOffset ne semble change pas en fonction DST.

Comment puis-je obtenir le bon moment avec la bonne valeur de décalage?

+9

+1 - il me rend fou que TimeZoneInfo.ConvertTimeBySystemTimeZoneId ne fonctionne pas seulement pour ce que je vois :) –

Répondre

47

Vous devez obtenir le UtcOffset du TimeZoneInfo, puis passez à la méthode que ToOffset():

var dt = DateTime.UtcNow; 
Console.WriteLine(dt.ToLocalTime()); 

var tz = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
var utcOffset = new DateTimeOffset(dt, TimeSpan.Zero); 
Console.WriteLine(utcOffset.ToOffset(tz.GetUtcOffset(utcOffset))); 
+0

... vous devez obtenir l'UTC décalage pour cette date spécifique le fuseau horaire. merci. – jaminto

+3

Ce n'est pas le meilleur moyen par rapport à [la réponse de Karl Gjertsen] (http://stackoverflow.com/a/16789973/57611) qui utilise une seule fonction .Net pour faire le travail au lieu d'extraire le décalage en créant un nouveau, jetez 'DateTimeOffset'. – ErikE

35

Vous pouvez également utiliser TimeZoneInfo.ConvertTimeFromUtc, ce qui permettra un gain de temps de la lumière du jour:

DateTime utc = DateTime.UtcNow; 
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time"); 
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(utc, zone); 
5

Ou mieux, si vous ne voulez pas coder en dur l'identificateur de fuseau horaire :

TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById(TimeZoneInfo.Local.Id); 
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(DateTime.UtcNow, tzi); 
+0

Ne pourriez-vous pas utiliser 'TimeZoneInfo.Local' directement? Pourquoi avez-vous besoin de l'appel de 'FindSystemTimeZoneById'? – CoderDennis

+1

Vous avez raison, nous n'en avons pas besoin. Nous pouvons simplement le faire comme ceci 'DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc (networkDateTime, TimeZoneInfo.Local); ' – Pabinator

+0

Mais alors vous êtes fixé à un seul fuseau horaire. Cela dépend de la façon dont vous voulez utiliser le code, je suppose. :-) –

1

Je suis un débutant à la fois .NET et StackOverflow, donc je peux me tromper, mais voilà:

L'utilisation TimeZoneInfo.ConvertTimeFromUtc permettra un gain de temps de la lumière du jour, et se convertir à l'heure en fonction du temps zone + un décalage possible de l'heure d'été. Cependant, le décalage lui-même dans l'objet résultant affichera le décalage pour l'heure standard, et ne tiendra pas compte de l'heure d'été. Donc, si vous voulez faire un ToString sur l'objet, vous vous retrouverez avec l'heure correcte (en heures et minutes), mais le mauvais décalage pendant l'heure d'été, ce qui peut conduire à un mauvais moment plus tard dans le code. Si vous utilisez à la place GetUtcOffset pour obtenir le décalage pour une heure spécifique, puis effectuez un ToOffset sur l'objet DateTimeOffset, les heures/minutes et le décalage lui-même seront correctement convertis et vous pouvez effectuer un ToString en toute sécurité .

string ExpectedDateTimePattern = "yyyy'-'MM'-'dd'T'HH':'mm':'ss''zzz"; 
string timeZoneId = "FLE Standard Time"; 
string dateTimestr = "2017-10-09T09:00:00+02:00"; 

DateTimeOffset dto = DateTimeOffset.Parse(dateTimeStr); 
TimeZoneInfo zone = TimeZoneInfo.FindSystemTimeZoneById(timeZoneId); 
TimeSpan offset = zone.GetUtcOffset(dto); 
dto = dto.ToOffset(offset); 
string localTime = dto.ToString(ExpectedDateTimePattern); 

localTime renverra «2017-10-09T10: 00: 00 + 03: 00».