Windows ve IANA saat dilimleri arasında nasıl çeviri yapılır?


156

Saat dilimi etiketi wikisinde açıklandığı gibi , iki farklı saat dilimi stili vardır.

  • Microsoft tarafından Windows ile kullanım için sağlananlar ve .Net TimeZoneInfosınıfı (Windows'ta çalışırken) gibi bir değerle tanımlanır "Eastern Standard Time".

  • TZDB'de IANA tarafından sağlananlar ve TimeZoneInfoLinux veya OSX üzerinde çalışırken .NET sınıfı tarafından kullanılanlar , gibi bir değerle tanımlanır "America/New_York".

Birçok İnternet tabanlı API, IANA saat dilimlerini kullanır, ancak çeşitli nedenlerden dolayı, bunu bir Windows saat dilimi kimliğine veya bunun tersine çevirmek gerekebilir.

Bu .Net'te nasıl başarılabilir?

Yanıtlar:


209

Windows ve IANA saat dilimi tanımlayıcıları arasında dönüşüm için birincil veri kaynağı , Unicode CLDR projesinin bir windowsZones.xmlparçası olarak dağıtılan dosyadır . En son geliştirme sürümü burada bulunabilir .

Bununla birlikte , CLDR yılda yalnızca iki kez yayınlanmaktadır. Bu, Windows güncellemelerinin periyodik kadansı ve IANA saat dilimi veritabanının düzensiz güncellemeleri ile birlikte, CLDR verilerini doğrudan kullanmayı karmaşık hale getirir. Saat dilimi değişikliklerinin, dünyanın çeşitli hükümetlerinin isteğine göre yapıldığını ve tüm değişikliklerin, ilgili yürürlük tarihlerinden önce bu sürüm döngülerine dahil edilmek için yeterli bildirimle yapılmadığını unutmayın.

Tam olarak CLDR tarafından kapsanmayan ve zaman zaman yenileri ortaya çıkan, ele alınması gereken birkaç başka uç durum vardır. Bu nedenle, çözümün karmaşıklığını Nuget'ten kurulabilen TimeZoneConverter mikro kitaplığına sığdırdım.

Bu kitaplığı kullanmak basittir. İşte bazı dönüştürme örnekleri:

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"

Proje sitesinde daha fazla örnek var .

Bir IANA saat dilimi tek bir Windows saat dilimiyle eşleştirilebilirken bunun tersinin doğru olmadığını bilmek önemlidir. Tek bir Windows saat dilimi, birden fazla IANA saat dilimiyle eşlenebilir. Bu, Eastern Standard Timehem America/New_Yorkve hem de için eşlenen yukarıdaki örneklerde görülebilir America/Toronto. TimeZoneConverter, "001"özel olarak bir ülke kodu sağlamazsanız ve o ülkedeki farklı bir bölge için bir eşleşme olmadıkça, CLDR'nin işaretlediği "altın bölge" olarak bilinen alanı teslim edecektir .

Not: Bu cevap yıllar içinde gelişti, bu nedenle aşağıdaki yorumlar mevcut revizyon için geçerli olabilir veya olmayabilir. Ayrıntılar için düzenleme geçmişini inceleyin. Teşekkürler.


1
dönüştürürken bu yöntemi kullanmak (GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi, Asia/Calcuttaolması gerektiğini verir Asia/Kolkata. TzdbDateTimeZoneSourceeski değerleri içeriyor gibi görünüyor .
Anto Subash

1
Dönüştürme sırasında @MattJohnson Asia/Kolkatakullanılarak IanaToWindows yöntemi, başarısız olur. ama Asia/Calcuttaeski adla çalışır . yöntemi güncellediniz WindowsToIanaama IanaToWindowsaynı problemi de yaşıyorsunuz . çalışmayan birkaç diğer bölgeler vardır America/Argentina/Buenos_Aires, America/Indiana/Indianapolis, Asia/Kathmandu.
Anto Subash

1
@AntoJSubash - Yine harika bir gözlem! IanaToWindowsTelafi etmek için yöntemi düzenledim . Çok teşekkürler!
Matt Johnson-Pint

2
@MattJohnson I ikinci @ sirrocco'nun gözlemi. Kanonik kimliği de var canonical = tzdbSource.CanonicalIdMap[ ianaZoneId ]; links = Enumerable.Repeat( canonical, 1 ).Concat( links );bu şekilde kullanmak benim için hile yaptı.
Johannes Rudolph

2
@sirrocco - Üzgünüm, yorumunuzu daha önce görmedim. Fonksiyonlar güncellendi. Teşekkürler!
Matt Johnson-Pint

4

Bunun eski bir soru olduğunu biliyorum, ancak arama yaparken bulduğum en alakalı gönderi olduğu için burada paylaşacağımı düşündüğüm bir kullanım örneğim vardı. Docker linux kapsayıcısı kullanarak bir .NET Core uygulaması geliştiriyordum, ancak bir Windows sunucusunda dağıtım için. Bu yüzden Windows saat dilimi adlarını desteklemek için yalnızca docker linux kapsayıcıma ihtiyacım vardı. Aşağıdakileri yaparak uygulama kodumu değiştirmeden bunu çalıştırdım:

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"

Ardından, .NET kodumda aşağıdakiler herhangi bir değişiklik yapılmadan çalıştı: TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time")


1
Bu oldukça harika bir ezber bozan düşünce! Birkaç belirli saat dilimini kapsadığınız sürece bu sorun olmayacak gibi görünüyor. ABD'de bu dörtten fazla olduğunu unutmayın. Günümüzde 50 eyaleti kapsamak America/Phoenixiçin "US Mountain Standard Time", Pacific/Honoluluto "Hawaiian Standard Time", America/Anchorageto "Alaskan Standard Time", to ve America/Adakto bağlantılarını da eklemeniz gerekir "Aleutian Standard Time". Bu, ABD topraklarını veya tarihsel tutarsızlıkları kapsamaz, ancak başlamanıza yardımcı olur.
Matt Johnson-Pint

2
Kişinin amacı tüm dünyayı kapsamaksa veya herhangi bir geçerli saat dilimi tanımlayıcısıyla uğraşmaksa bu yaklaşımı tavsiye etmem. Liste bunun için çok uzun ve çok uçucu.
Matt Johnson-Pint
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.