172 votes

Comment traduire les fuseaux horaires de Windows et de l'IANA ?

Comme décrit dans la balise de fuseau horaire wiki il existe deux styles différents de fuseaux horaires.

  • Ceux fournis par Microsoft pour une utilisation avec Windows et le .Net TimeZoneInfo (lorsqu'ils fonctionnent sous Windows) sont identifiés par une valeur telle que "Eastern Standard Time" .

  • Ceux fournis par l'IANA dans la TZDB, et utilisés par le programme .NET. TimeZoneInfo lorsqu'ils fonctionnent sous Linux ou OSX, sont identifiés par une valeur telle que "America/New_York" .

De nombreuses API basées sur Internet utilisent les fuseaux horaires de l'IANA, mais pour de nombreuses raisons, il peut être nécessaire de les convertir en un identifiant de fuseau horaire Windows, ou vice-versa.

Comment cela peut-il être réalisé en .Net ?

232voto

Matt Johnson Points 33433

La source principale des données pour la conversion entre les identifiants de fuseaux horaires de Windows et de l'IANA est la base de données de l'IANA. windowsZones.xml distribué dans le cadre du programme le CLDR d'Unicode projet. La dernière version de développement peut être trouvée aquí .

Cependant Le CLDR n'est publié que deux fois par an. Ceci, ajouté à la cadence périodique des mises à jour de Windows et aux mises à jour irrégulières de la base de données des fuseaux horaires de l'IANA, complique l'utilisation directe des données du CLDR. Gardez à l'esprit que les changements de fuseaux horaires sont effectués selon les caprices des différents gouvernements du monde, et que tous les changements ne sont pas effectués avec suffisamment de préavis pour être intégrés dans ces cycles de publication avant leurs dates d'entrée en vigueur respectives.

Il y a quelques autres cas particuliers qui doivent être traités et qui ne sont pas strictement couverts par le CLDR, et de nouveaux cas apparaissent de temps en temps. Par conséquent, j'ai encapsulé la complexité de la solution dans le fichier TimeZoneConverter qui peut être installée à partir de Nuget.

L'utilisation de cette bibliothèque est simple. Voici quelques exemples de conversion :

string tz = TZConvert.IanaToWindows("America/New_York");
// Result:  "Eastern Standard Time"

string tz = TZConvert.WindowsToIana("Eastern Standard Time");
// result:  "America/New_York"

string tz = TZConvert.WindowsToIana("Eastern Standard Time", "CA");
// result:  "America/Toronto"

Il existe d'autres exemples sur le site du projet .

Il est important de reconnaître que si un fuseau horaire IANA peut être mis en correspondance avec un fuseau horaire Windows unique, l'inverse n'est pas vrai. Un seul fuseau horaire Windows peut être associé à plus d'un fuseau horaire IANA. C'est ce que l'on peut constater dans les exemples ci-dessus, où Eastern Standard Time est mis en correspondance avec les deux America/New_York et à America/Toronto . TimeZoneConverter livrera celui que CLDR marque avec "001" Il s'agit de la "zone dorée", à moins que vous ne fournissiez spécifiquement un code de pays et qu'il existe une correspondance pour une zone différente dans ce pays.

Remarque : cette réponse a évolué au fil des ans. Les commentaires ci-dessous peuvent donc s'appliquer ou non à la révision actuelle. Consultez l'historique des modifications pour plus de détails. Merci.

0 votes

JonSkeet J'étais fatigué de me répéter. J'ai pensé que je devrais essayer un post du style "répondez à votre propre question".

0 votes

À quoi fait référence la version de nodatime ?

0 votes

@shyamnathan - Cela nécessite la version 1.1.0 ou supérieure de Noda Time.

5voto

Toby J Points 942

À partir de .NET 6 Preview 4, c'est enfin possible pour travailler avec les fuseaux horaires de manière multiplateforme, de sorte que ces solutions de contournement manuelles ne sont plus nécessaires.

El TimeZoneInfo.FindSystemTimeZoneById(string) accepte automatiquement les fuseaux horaires Windows ou IANA sur l'une ou l'autre plateforme et les convertit si nécessaire.

// Both of these will now work on any supported OS where ICU and time zone data are available.
TimeZoneInfo tzi1 = TimeZoneInfo.FindSystemTimeZoneById("AUS Eastern Standard Time");
TimeZoneInfo tzi2 = TimeZoneInfo.FindSystemTimeZoneById("Australia/Sydney");

Notez que, comme indiqué sur le lien, les images Docker de .NET Core Alpine basées sur Linux ne disposent pas de la tzdata installé par défaut Il doit donc être installé dans votre Dockerfile pour que cela fonctionne correctement.

4voto

EverPresent Points 1298

Je sais que c'est une vieille question, mais j'avais un cas d'utilisation que j'ai pensé partager ici, puisque c'est l'article le plus pertinent que j'ai trouvé en cherchant. Je développais une application .NET Core en utilisant un conteneur docker linux, mais pour un déploiement sur un serveur Windows. J'avais donc seulement besoin que mon conteneur docker linux prenne en charge les noms de fuseaux horaires de Windows. J'ai réussi à le faire fonctionner sans modifier le code de mon application en procédant comme suit :

cp /usr/share/zoneinfo/America/Chicago "/usr/share/zoneinfo/Central Standard Time"
cp /usr/share/zoneinfo/America/New_York "/usr/share/zoneinfo/Eastern Standard Time"
cp /usr/share/zoneinfo/America/Denver "/usr/share/zoneinfo/Mountain Standard Time"
cp /usr/share/zoneinfo/America/Los_Angeles "/usr/share/zoneinfo/Pacific Standard Time"

Ensuite, dans mon code .NET, ce qui suit a fonctionné sans aucune modification : TimeZoneInfo.FindSystemTimeZoneById("Central Standard 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