52 votes

Obtenir l'heure d'un autre fuseau horaire sans tenir compte du fuseau horaire local

Quel que soit le fuseau horaire local de l'utilisateur, je dois, en utilisant C# (.NET 2.0), déterminer l'heure (objet DateTime) dans le fuseau horaire de l'Est.

Je connais ces méthodes, mais il ne semble pas y avoir de moyen évident d'obtenir un objet DateTime pour un fuseau horaire différent de celui dans lequel se trouve l'utilisateur.

 DateTime.Now
 DateTime.UtcNow
 TimeZone.CurrentTimeZone

Bien entendu, la solution doit tenir compte de l'heure d'été.

101voto

Marc Gravell Points 482669

Dans .NET 3.5, il y a TimeZoneInfo qui fournit de nombreuses fonctionnalités dans ce domaine ; la version 2.0SP1 dispose de DateTimeOffset mais elle est beaucoup plus limitée.

Obtenir UtcNow et l'ajout d'un décalage fixe fait partie du travail, mais ne tient pas compte de l'heure d'été.

Donc en 3.5 je pense que vous pouvez faire quelque chose comme :

DateTime eastern = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(
    DateTime.UtcNow, "Eastern Standard Time");

Mais cela n'existe tout simplement pas dans la version 2.0 ; désolé.

8voto

Andy Points 756

Comme tout le monde l'a mentionné, .NET 2 ne contient pas d'informations sur les fuseaux horaires. Cependant, ces informations sont stockées dans le registre et il est assez facile d'écrire une classe d'encapsulation autour d'elles :

LOGICIEL \Microsoft\Windows NT \CurrentVersion\Time Zones

contient des sous-clés pour tous les fuseaux horaires. La valeur du champ TZI contient toutes les propriétés de transition et de biais pour un fuseau horaire, mais tout cela est stocké dans un tableau binaire. Les bits les plus importants (biais et lumière du jour), sont des int32 stockés aux positions 0 et 8 respectivement :

int bias = BitConverter.ToInt32((byte[])tzKey.GetValue("TZI"), 0);
int daylightBias = BitConverter.ToInt32((byte[])tzKey.GetValue("TZI"), 8);

Cette page contient un résumé raisonnable : http://burks.brighton.ac.uk/burks/language/pascal/uddf/pages/registry.htm

8voto

De - http://msdn.microsoft.com/en-us/library/system.timezoneinfo.converttimefromutc.aspx

Cela permet de retrouver un fuseau horaire par son nom, au cas où les États-Unis se retrouveraient à 15 degrés à l'ouest ou à l'est du méridien de Londres.

DateTime timeUtc = DateTime.UtcNow;
try
{
   TimeZoneInfo cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
   DateTime cstTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, cstZone);
   Console.WriteLine("The date and time are {0} {1}.", 
                     cstTime, 
                     cstZone.IsDaylightSavingTime(cstTime) ?
                             cstZone.DaylightName : cstZone.StandardName);
}
catch (TimeZoneNotFoundException)
{
   Console.WriteLine("The registry does not define the Central Standard Time zone.");
}                           
catch (InvalidTimeZoneException)
{
   Console.WriteLine("Registry data on the Central STandard Time zone has been corrupted.");
}

2voto

Robert C. Barth Points 9788

Je vais vous faire gagner du temps et vous dire qu'il n'y a aucun moyen dans .net proprement dit, version 2.0, d'obtenir un objet DateTime pour un autre fuseau horaire que celui sur lequel le logiciel fonctionne (autre que UTC).

Toutefois, cela ne signifie pas qu'il n'existe pas de moyen de le faire en dehors de .net. Jetez un coup d'oeil aquí à la classe TimeZoneInformation. Cette classe enveloppe quelques trucs p/invoke au système d'exploitation Win pour obtenir les informations de fuseau horaire du système d'exploitation. Je l'ai utilisée avec succès à l'époque de la nouvelle version 2.0 et elle a très bien fonctionné. Le site sur lequel je travaillais devait être capable d'afficher toutes les dates et heures locales pour l'utilisateur et devait tenir compte de l'heure d'été, et cette classe a fait l'affaire pour nous.

1voto

Charles Bretana Points 59899

Et si

 DateTime lclTime = DateTime.Now;
 DateTime ept = lclTime.ToUniversalTime().AddHours(
                   IsEasternDaylightSavingTime(
                       lclTime.ToUniversalTime())? -5: -4)

ou si vous avez déjà un UTC local, il suffit de

 DateTime lclUtc = DateTime.UtcNow;
 DateTime ept = lclUtc.AddHours(
                  IsEasternDaylightSavingTime(lclUtc)? -5: -4)

Utiliser un dictionnaire statique de valeurs codées en dur pour les dates de printemps et d'automne de l'heure de l'Est pour les 50 prochaines années... Cela ne représente que 300 octets environ... puis indexer dans ce dictionnaire pour déterminer si c'est l'heure d'été sur la côte Est... Comme indiqué, vous ne vous souciez pas de savoir si c'est l'heure d'été dans la zone locale ou non...

 private static bool IsEasternDaylightSavingTime(DateTime utcDateTime)
   {
        // hard coded method to determine 
        // whether utc datetime is Eastern Standard time
        // or Eastern Daylight Time
   }

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