web-dev-qa-db-fra.com

Comment traduire entre Windows et les fuseaux horaires IANA?

Comme décrit dans la balise timezone wiki , il existe deux styles de fuseaux horaires.

  • Celles fournies par Microsoft pour une utilisation avec Windows et la classe .Net TimeZoneInfo sont identifiées par une valeur telle que Eastern Standard Time.

  • Celles fournies par l'IANA dans la TZDB sont identifiées par une valeur telle que America/New_York.

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

Comment cela peut-il être accompli en .Net?

132
Matt Johnson-Pint

La source principale des données pour la conversion entre les identificateurs de fuseau horaire Windows et IANA est le windowsZones.xml fichier, distribué dans le cadre du projet le projet Unicode CLDR .

Cependant , CLDR n'est publié que deux fois par an. Ceci, ainsi que la cadence périodique des mises à jour Windows et les mises à jour irrégulières de la base de données de fuseaux horaires IANA, compliquent l'utilisation directe des données CLDR. N'oubliez pas que les changements de fuseau horaire sont eux-mêmes opérés à la demande des différents gouvernements du monde et que tous les changements ne sont pas effectués avec un préavis suffisant pour être intégrés à ces cycles de publication avant leurs dates effectives respectives.

Il y a quelques autres cas Edge à traiter qui ne sont pas couverts de manière stricte par le CLDR, et de nouveaux cas apparaissent de temps à autre. Par conséquent, j'ai intégré la complexité de la solution dans la micro-bibliothèque TimeZoneConverter , qui peut être installée à partir de Nuget.

Utiliser 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 y a plus d'exemples sur le site du projet .

Il est important de reconnaître que si un fuseau horaire IANA peut être mappé sur un seul fuseau horaire Windows, l'inverse n'est pas vrai. Un seul fuseau horaire Windows peut être associé à plusieurs fuseaux horaires IANA. Cela se voit dans les exemples ci-dessus, où Eastern Standard Time est associé à la fois America/New_York, et à America/Toronto. TimeZoneConverter livrera celui qui marque le CLDR avec "001", appelée "zone dorée", à moins que vous ne fournissiez un code de pays spécifique et qu'il y ait correspondance pour une zone différente dans ce pays.

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

170
Matt Johnson-Pint

Je sais que c’est une vieille question, mais j’avais un cas d’utilisation que j’aimerais partager ici, car c’est le message le plus pertinent que j’ai trouvé lors de la recherche. Je développais une application .NET Core à l'aide d'un conteneur Linux Docker, mais pour le déploiement sur un serveur Windows. Je n’avais donc besoin que de mon conteneur Linux Docker pour prendre en charge les noms de fuseau horaire Windows. Je travaille sans changer mon code d'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, les éléments suivants ont fonctionné sans aucune modification: TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")

2
EverPresent