将Microsoft Timezone转换为rails中的标准时区数据

我有一个连接到SQL Server数据库的rails应用程序,并且有一个连接到同一个数据库的Windows桌面应用程序。 Windows应用程序正在使用Microsoft Windows时区数据库,因此我获得了像Pacific Daylight Time这样的时区名称。 在rails中, ActiveSupport::TimeZone类为我们提供了一个映射哈希,其中键将类似于Pacific Time (US & Canada) ,其值将类似于America/Los_Angeles 。 有什么东西可以将Windows格式转换为标准格式,所以我可以使用Time.zone吗?

或者是否有时区gem可以让我配置rails来使用windows格式?

这是一个我已经开始帮助转换的数组,但有一点我不是100%肯定。

  DAYLIGHT = [ {name: 'Dateline Daylight Time', offset: -12, alt: 'International Date Line West'}, {name: 'UTC-11', offset: -11, alt: ''}, {name: 'Hawaiian Daylight Time', offset: -10, alt: 'Hawaii'}, {name: 'Alaskan Daylight Time', offset: -9, alt: 'Alaska'}, {name: 'Pacific Daylight Time (Mexico)', offset: -8, alt: ''}, {name: 'Pacific Daylight Time', offset: -8, alt: 'Pacific Time (US & Canada)'}, {name: 'US Mountain Daylight Time', offset: -7, alt: 'Mountain Time (US & Canada)'}, {name: 'Mountain Daylight Time (Mexico)', offset: -7, alt: ''}, {name: 'Mountain Daylight Time', offset: -7, alt: 'Mountain Time (US & Canada)'}, {name: 'Central America Daylight Time', offset: -6, alt: 'Central Time (US & Canada)'}, {name: 'Central Daylight Time', offset: -6, alt: 'Central Time (US & Canada)'}, {name: 'Central Daylight Time (Mexico)', offset: -6, alt: ''}, {name: 'Canada Central Daylight Time', offset: -6, alt: ''}, {name: 'SA Pacific Daylight Time', offset: -5, alt: ''}, {name: 'Eastern Daylight Time', offset: -5, alt: 'Eastern Time (US & Canada)'}, {name: 'US Eastern Daylight Time', offset: -5, alt: 'Eastern Time (US & Canada)'}, {name: 'Venezuela Daylight Time', offset: -4.5, alt: ''}, {name: 'Paraguay Daylight Time', offset: -4, alt: ''}, {name: 'Atlantic Daylight Time', offset: -4, alt: ''}, {name: 'Central Brazilian Daylight Time', offset: -4, alt: ''}, {name: 'SA Western Daylight Time', offset: -4, alt: ''}, {name: 'Pacific SA Daylight Time', offset: -4, alt: ''}, {name: 'Newfoundland Daylight Time', offset: -3.5, alt: ''}, {name: 'E. South America Daylight Time', offset: -3, alt: ''}, {name: 'Argentina Daylight Time', offset: -3, alt: ''}, {name: 'SA Eastern Daylight Time', offset: -3, alt: ''}, {name: 'Greenland Daylight Time', offset: -3, alt: ''}, {name: 'Montevideo Daylight Time', offset: -3, alt: ''}, {name: 'Bahia Daylight Time', offset: -3, alt: ''}, {name: 'UTC-02', offset: -2, alt: ''}, {name: 'Mid-Atlantic Daylight Time', offset: -2, alt: ''}, {name: 'Azores Daylight Time', offset: -1, alt: ''}, {name: 'Cabo Verde Daylight Time', offset: -1, alt: ''}, {name: 'Morocco Daylight Time', offset: 0, alt: ''}, {name: 'Coordinated Universal Time', offset: 0, alt: ''}, {name: 'GMT Daylight Time', offset: 0, alt: ''}, {name: 'Greenwich Daylight Time', offset: 0, alt: ''}, {name: 'W. Europe Daylight Time', offset: 1, alt: ''}, {name: 'Central Europe Daylight Time', offset: 1, alt: ''}, {name: 'Romance Daylight Time', offset: 1, alt: ''}, {name: 'Central European Daylight Time', offset: 1, alt: ''}, {name: 'W. Central Africa Daylight Time', offset: 1, alt: ''}, {name: 'Namibia Daylight Time', offset: 1, alt: ''}, {name: 'Jordan Daylight Time', offset: 2, alt: ''}, {name: 'GTB Daylight Time', offset: 2, alt: ''}, {name: 'Middle East Daylight Time', offset: 2, alt: ''}, {name: 'Egypt Daylight Time', offset: 2, alt: ''}, {name: 'Syria Daylight Time', offset: 2, alt: ''}, {name: 'E. Europe Daylight Time', offset: 2, alt: ''}, {name: 'South Africa Daylight Time', offset: 2, alt: ''}, {name: 'FLE Daylight Time', offset: 2, alt: ''}, {name: 'Turkey Daylight Time', offset: 2, alt: ''}, {name: 'Jerusalem Daylight Time', offset: 2, alt: ''}, {name: 'Russia TZ 1 Daylight Time', offset: 2, alt: ''}, {name: 'Libya Daylight Time', offset: 2, alt: ''}, {name: 'Arabic Daylight Time', offset: 3, alt: ''}, {name: 'Arab Daylight Time', offset: 3, alt: ''}, {name: 'Belarus Daylight Time', offset: 3, alt: ''}, {name: 'Russia TZ 2 Daylight Time', offset: 3, alt: ''}, {name: 'E. Africa Daylight Time', offset: 3, alt: ''}, {name: 'Iran Daylight Time', offset: 3.5, alt: ''}, {name: 'Arabian Daylight Time', offset: 4, alt: ''}, {name: 'Azerbaijan Daylight Time', offset: 4, alt: ''}, {name: 'Russia TZ 3 Daylight Time', offset: 4, alt: ''}, {name: 'Mauritius Daylight Time', offset: 4, alt: ''}, {name: 'Georgian Daylight Time', offset: 4, alt: ''}, {name: 'Caucasus Daylight Time', offset: 4, alt: ''}, {name: 'Afghanistan Daylight Time', offset: 4.5, alt: ''}, {name: 'West Asia Daylight Time', offset: 5, alt: ''}, {name: 'Russia TZ 4 Daylight Time', offset: 5, alt: ''}, {name: 'Pakistan Daylight Time', offset: 5, alt: ''}, {name: 'India Daylight Time', offset: 5.5, alt: ''}, {name: 'Sri Lanka Daylight Time', offset: 5.5, alt: ''}, {name: 'Nepal Daylight Time', offset: 5.75, alt: ''}, {name: 'Central Asia Daylight Time', offset: 6, alt: ''}, {name: 'Bangladesh Daylight Time', offset: 6, alt: ''}, {name: 'Russia TZ 5 Daylight Time', offset: 6, alt: ''}, {name: 'Myanmar Daylight Time', offset: 6.5, alt: ''}, {name: 'SE Asia Daylight Time', offset: 7, alt: ''}, {name: 'Russia TZ 6 Daylight Time', offset: 7, alt: ''}, {name: 'China Daylight Time', offset: 8, alt: ''}, {name: 'Russia TZ 7 Daylight Time', offset: 8, alt: ''}, {name: 'Malay Peninsula Daylight Time', offset: 8, alt: ''}, {name: 'W. Australia Daylight Time', offset: 8, alt: ''}, {name: 'Taipei Daylight Time', offset: 8, alt: ''}, {name: 'Ulaanbaatar Daylight Time', offset: 8, alt: ''}, {name: 'Tokyo Daylight Time', offset: 9, alt: ''}, {name: 'Korea Daylight Time', offset: 9, alt: ''}, {name: 'Russia TZ 8 Daylight Time', offset: 9, alt: ''}, {name: 'Cen. Australia Daylight Time', offset: 9.5, alt: ''}, {name: 'AUS Central Daylight Time', offset: 9.5, alt: ''}, {name: 'E. Australia Daylight Time', offset: 10, alt: ''}, {name: 'AUS Eastern Daylight Time', offset: 10, alt: ''}, {name: 'West Pacific Daylight Time', offset: 10, alt: ''}, {name: 'Tasmania Daylight Time', offset: 10, alt: ''}, {name: 'Magadan Daylight Time', offset: 10, alt: ''}, {name: 'Russia TZ 9 Daylight Time', offset: 10, alt: ''}, {name: 'Russia TZ 10 Daylight Time', offset: 11, alt: ''}, {name: 'Central Pacific Daylight Time', offset: 11, alt: ''}, {name: 'Russia TZ 11 Daylight Time', offset: 12, alt: ''}, {name: 'New Zealand Daylight Time', offset: 12, alt: ''}, {name: 'UTC+12', offset: 12, alt: ''}, {name: 'Fiji Daylight Time', offset: 12, alt: ''}, {name: 'Kamchatka Daylight Time', offset: 12, alt: ''}, {name: 'Tonga Daylight Time', offset: 13, alt: ''}, {name: 'Samoa Daylight Time', offset: 13, alt: ''}, {name: 'Line Islands Daylight Time', offset: 14, alt: ''} ] 

改进的答案

我的原始答案(下面)中描述的function现在可以在我的TimeZoneConverter库中找到。 所有艰苦的工作都是为您完成的,并随着世界时区的变化而不断更新。 项目自述文件中的示例显示了如何在Windows,IANA和Rails标识符之间进行转换。

由于问题中描述的应用程序是在Rails中,我建议在.NET中运行后台作业,将Windows时区ID转换为Rails应用程序中所需的ID,并将它们保存在单独的列中。


原始答案

您正在寻找的资源是作为Unicode CLDR项目的一部分维护的Windows到IANA映射文件。 该文件位于common/supplemental/windowsZones.xml的CLDR版本中,您可以在此处找到它的当前“开发版本”。

注意以下几点:

  • 随着新的时区从Microsoft和IANA发布,或者有时政府更改其时区规则以适应不同的映射,该文件确实会更新。

  • 列表中的偏移量只是标准偏移量 – 即夏令时无效时适用的偏移量。 “时区”由标准偏移,日光偏移,DST过渡的特定日期和时间以及偏移和过渡的变化历史组成。

  • Rails时区名称不应该在Rails之外的任何地方使用。 我的理解是它们实际上是 Rails决定使用标准的IANA / Olson时区之前创建的,然后当Ruby tzinfo gem变得可行时,Rails区域通过本页显示的MAPPING常量进行了改造,然后一些被添加为个人投诉出现了。 如果可能,只需通过tzinfo gem直接使用IANA时区。 如果没有,那么您将有两层映射(Microsoft – > IANA – > Rails)。

  • 我不知道CLDR映射的特定于Rails的实现。 我检查了几个CLDR for Rails项目,发现它们没有包含CLDR的特定部分。 但是,如果您可以控制Windows方面的内容,那么您可以考虑使用我在此答案中描述的.NET实现。 您可以在Windows端进行Windows到IANA转换,然后直接使用tzinfo使用IANA区域,或映射到Rails应用程序中的Rails区域。

  • 还要意识到Rails时区的数量明显少于IANA支持的时区数量。 我没有检查过,但有些Windows区域可能会映射到不在Rails中的IANA区域。 此外,还有一些Rails区域具有多个Rails条目,但只有一个IANA映射 – 实质上使它们成为等效的别名。

  • Rails和Windows都使用“UTC”作为区域ID,Rails映射到“Etc / UTC”,但CLDR映射到“Etc / GMT”。 你必须手动处理这个。

  • 最后,要认识到CLDR使用“稳定”标识符的方式与IANA的“规范”标识符不同,这可能会在映射过程中造成一些困难。

    • 例如,考虑到Microsoft区域“印度标准时间”映射到CLDR中的“Asia / Calcutta”,因为这就是原始 IANA区域。 但是,IANA将该区域更改为“Asia / Kolkata”,并为“Asia / Calcutta”设置了向后兼容的链接。 当您查看Rails MAPPING常量时,有四个Rails区域,“Chennai”,“Kolkata”,“Mumbai”和“New Delhi” – 所有这些区域都映射到“Asia / Kolkata”。

    • 为了解决这个问题,您需要CLDR中的另一个文件common/bcp47/timezone.xml 。 您可以使用此文件查找别名IANA区域之间的所有链接,这可以帮助您映射回Rails区域。

所以是的,这是可能的 – 但这并不容易。 ;)

我已经为你执行了当前的映射,如下所示:

 "Windows","IANA","Rails" "W. Central Africa Standard Time","Africa/Algiers","West Central Africa" "Egypt Standard Time","Africa/Cairo","Cairo" "Morocco Standard Time","Africa/Casablanca","Casablanca" "South Africa Standard Time","Africa/Harare","Harare" "South Africa Standard Time","Africa/Johannesburg","Pretoria" "Greenwich Standard Time","Africa/Monrovia","Monrovia" "E. Africa Standard Time","Africa/Nairobi","Nairobi" "Argentina Standard Time","America/Argentina/Buenos_Aires","Buenos Aires" "SA Pacific Standard Time","America/Bogota","Bogota" "Venezuela Standard Time","America/Caracas","Caracas" "Central Standard Time","America/Chicago","Central Time (US & Canada)" "Mountain Standard Time (Mexico)","America/Chihuahua","Chihuahua" "Mountain Standard Time","America/Denver","Mountain Time (US & Canada)" "Greenland Standard Time","America/Godthab","Greenland" "Central America Standard Time","America/Guatemala","Central America" "SA Western Standard Time","America/Guyana","Georgetown" "Atlantic Standard Time","America/Halifax","Atlantic Time (Canada)" "US Eastern Standard Time","America/Indiana/Indianapolis","Indiana (East)" "Alaskan Standard Time","America/Juneau","Alaska" "SA Western Standard Time","America/La_Paz","La Paz" "SA Pacific Standard Time","America/Lima","Lima" "SA Pacific Standard Time","America/Lima","Quito" "Pacific Standard Time","America/Los_Angeles","Pacific Time (US & Canada)" "Mountain Standard Time (Mexico)","America/Mazatlan","Mazatlan" "Central Standard Time (Mexico)","America/Mexico_City","Guadalajara" "Central Standard Time (Mexico)","America/Mexico_City","Mexico City" "Central Standard Time (Mexico)","America/Monterrey","Monterrey" "Montevideo Standard Time","America/Montevideo","Montevideo" "Eastern Standard Time","America/New_York","Eastern Time (US & Canada)" "US Mountain Standard Time","America/Phoenix","Arizona" "Canada Central Standard Time","America/Regina","Saskatchewan" "Pacific SA Standard Time","America/Santiago","Santiago" "E. South America Standard Time","America/Sao_Paulo","Brasilia" "Newfoundland Standard Time","America/St_Johns","Newfoundland" "Pacific Standard Time","America/Tijuana","Tijuana" "Central Asia Standard Time","Asia/Almaty","Almaty" "Arabic Standard Time","Asia/Baghdad","Baghdad" "Azerbaijan Standard Time","Asia/Baku","Baku" "SE Asia Standard Time","Asia/Bangkok","Bangkok" "SE Asia Standard Time","Asia/Bangkok","Hanoi" "China Standard Time","Asia/Chongqing","Chongqing" "Sri Lanka Standard Time","Asia/Colombo","Sri Jayawardenepura" "Bangladesh Standard Time","Asia/Dhaka","Astana" "Bangladesh Standard Time","Asia/Dhaka","Dhaka" "China Standard Time","Asia/Hong_Kong","Hong Kong" "North Asia East Standard Time","Asia/Irkutsk","Irkutsk" "SE Asia Standard Time","Asia/Jakarta","Jakarta" "Israel Standard Time","Asia/Jerusalem","Jerusalem" "Afghanistan Standard Time","Asia/Kabul","Kabul" "Russia Time Zone 11","Asia/Kamchatka","Kamchatka" "Pakistan Standard Time","Asia/Karachi","Islamabad" "Pakistan Standard Time","Asia/Karachi","Karachi" "Nepal Standard Time","Asia/Kathmandu","Kathmandu" "India Standard Time","Asia/Kolkata","Chennai" "India Standard Time","Asia/Kolkata","Kolkata" "India Standard Time","Asia/Kolkata","Mumbai" "India Standard Time","Asia/Kolkata","New Delhi" "North Asia Standard Time","Asia/Krasnoyarsk","Krasnoyarsk" "Singapore Standard Time","Asia/Kuala_Lumpur","Kuala Lumpur" "Arab Standard Time","Asia/Kuwait","Kuwait" "Magadan Standard Time","Asia/Magadan","Magadan" "Arabian Standard Time","Asia/Muscat","Abu Dhabi" "Arabian Standard Time","Asia/Muscat","Muscat" "N. Central Asia Standard Time","Asia/Novosibirsk","Novosibirsk" "Myanmar Standard Time","Asia/Rangoon","Rangoon" "Arab Standard Time","Asia/Riyadh","Riyadh" "Korea Standard Time","Asia/Seoul","Seoul" "China Standard Time","Asia/Shanghai","Beijing" "Singapore Standard Time","Asia/Singapore","Singapore" "Russia Time Zone 10","Asia/Srednekolymsk","Srednekolymsk" "Taipei Standard Time","Asia/Taipei","Taipei" "West Asia Standard Time","Asia/Tashkent","Tashkent" "Georgian Standard Time","Asia/Tbilisi","Tbilisi" "Iran Standard Time","Asia/Tehran","Tehran" "Tokyo Standard Time","Asia/Tokyo","Osaka" "Tokyo Standard Time","Asia/Tokyo","Sapporo" "Tokyo Standard Time","Asia/Tokyo","Tokyo" "Ulaanbaatar Standard Time","Asia/Ulaanbaatar","Ulaanbaatar" "Central Asia Standard Time","Asia/Urumqi","Urumqi" "Vladivostok Standard Time","Asia/Vladivostok","Vladivostok" "Yakutsk Standard Time","Asia/Yakutsk","Yakutsk" "Ekaterinburg Standard Time","Asia/Yekaterinburg","Ekaterinburg" "Caucasus Standard Time","Asia/Yerevan","Yerevan" "Azores Standard Time","Atlantic/Azores","Azores" "Cape Verde Standard Time","Atlantic/Cape_Verde","Cape Verde Is." "UTC-02","Atlantic/South_Georgia","Mid-Atlantic" "Cen. Australia Standard Time","Australia/Adelaide","Adelaide" "E. Australia Standard Time","Australia/Brisbane","Brisbane" "AUS Central Standard Time","Australia/Darwin","Darwin" "Tasmania Standard Time","Australia/Hobart","Hobart" "AUS Eastern Standard Time","Australia/Melbourne","Canberra" "AUS Eastern Standard Time","Australia/Melbourne","Melbourne" "W. Australia Standard Time","Australia/Perth","Perth" "AUS Eastern Standard Time","Australia/Sydney","Sydney" "UTC","Etc/UTC","UTC" "W. Europe Standard Time","Europe/Amsterdam","Amsterdam" "GTB Standard Time","Europe/Athens","Athens" "Central Europe Standard Time","Europe/Belgrade","Belgrade" "W. Europe Standard Time","Europe/Berlin","Berlin" "W. Europe Standard Time","Europe/Berlin","Bern" "Central Europe Standard Time","Europe/Bratislava","Bratislava" "Romance Standard Time","Europe/Brussels","Brussels" "GTB Standard Time","Europe/Bucharest","Bucharest" "Central Europe Standard Time","Europe/Budapest","Budapest" "Romance Standard Time","Europe/Copenhagen","Copenhagen" "GMT Standard Time","Europe/Dublin","Dublin" "FLE Standard Time","Europe/Helsinki","Helsinki" "Turkey Standard Time","Europe/Istanbul","Istanbul" "Kaliningrad Standard Time","Europe/Kaliningrad","Kaliningrad" "FLE Standard Time","Europe/Kiev","Kyiv" "GMT Standard Time","Europe/Lisbon","Lisbon" "Central Europe Standard Time","Europe/Ljubljana","Ljubljana" "GMT Standard Time","Europe/London","Edinburgh" "GMT Standard Time","Europe/London","London" "Romance Standard Time","Europe/Madrid","Madrid" "Belarus Standard Time","Europe/Minsk","Minsk" "Russian Standard Time","Europe/Moscow","Moscow" "Russian Standard Time","Europe/Moscow","St. Petersburg" "Romance Standard Time","Europe/Paris","Paris" "Central Europe Standard Time","Europe/Prague","Prague" "FLE Standard Time","Europe/Riga","Riga" "W. Europe Standard Time","Europe/Rome","Rome" "Russia Time Zone 3","Europe/Samara","Samara" "Central European Standard Time","Europe/Sarajevo","Sarajevo" "Central European Standard Time","Europe/Skopje","Skopje" "FLE Standard Time","Europe/Sofia","Sofia" "W. Europe Standard Time","Europe/Stockholm","Stockholm" "FLE Standard Time","Europe/Tallinn","Tallinn" "W. Europe Standard Time","Europe/Vienna","Vienna" "FLE Standard Time","Europe/Vilnius","Vilnius" "Russian Standard Time","Europe/Volgograd","Volgograd" "Central European Standard Time","Europe/Warsaw","Warsaw" "Central European Standard Time","Europe/Zagreb","Zagreb" "Samoa Standard Time","Pacific/Apia","Samoa" "New Zealand Standard Time","Pacific/Auckland","Auckland" "New Zealand Standard Time","Pacific/Auckland","Wellington" "Tonga Standard Time","Pacific/Fakaofo","Tokelau Is." "Fiji Standard Time","Pacific/Fiji","Fiji" "Central Pacific Standard Time","Pacific/Guadalcanal","Solomon Is." "West Pacific Standard Time","Pacific/Guam","Guam" "Hawaiian Standard Time","Pacific/Honolulu","Hawaii" "UTC+12","Pacific/Majuro","Marshall Is." "UTC-11","Pacific/Midway","International Date Line West" "UTC-11","Pacific/Midway","Midway Island" "Central Pacific Standard Time","Pacific/Noumea","New Caledonia" "UTC-11","Pacific/Pago_Pago","American Samoa" "West Pacific Standard Time","Pacific/Port_Moresby","Port Moresby" "Tonga Standard Time","Pacific/Tongatapu","Nuku'alofa" 

请注意,上面的列表包含多个Rails区域映射回同一Windows区域的条目。 在Windows-to-Rails方向映射时,您可能只想选择其中一个。

此外,上面的列表不包括无法映射的区域,如下所示(CSV):

 "Windows","IANA","Rails" "","Pacific/Chatham","Chatham Is." "Dateline Standard Time","Etc/GMT+12","" "Pacific Standard Time (Mexico)","America/Santa_Isabel","" "Eastern Standard Time (Mexico)","America/Cancun","" "Paraguay Standard Time","America/Asuncion","" "Central Brazilian Standard Time","America/Cuiaba","" "SA Eastern Standard Time","America/Cayenne","" "Bahia Standard Time","America/Bahia","" "Namibia Standard Time","Africa/Windhoek","" "Jordan Standard Time","Asia/Amman","" "Middle East Standard Time","Asia/Beirut","" "Syria Standard Time","Asia/Damascus","" "E. Europe Standard Time","Etc/GMT-2","" "Libya Standard Time","Africa/Tripoli","" "Mauritius Standard Time","Indian/Mauritius","" "Line Islands Standard Time","Pacific/Kiritimati",""