Method to convert Windows time zones to IANA time zone database in PowerShell

I wasn’t able to find a good method for converting windows time zones to the IANA format I needed. This method isn’t perfect but it gets the job done for my purposes.

First you need to get the windowsZones.xml file from:
https://github.com/unicode-org/cldr/blob/main/common/supplemental/windowsZones.xml

The following PowerShell script converts the XML into the body of the switch statement used in the lookup script. This is based on another script I found here on StackOverflow.

# https://github.com/unicode-org/cldr/blob/main/common/supplemental/windowsZones.xml

# Download the xml file.
[Xml]$xml = Get-Content -Path "windowsZones.xml"

# Parse the fields we want from the XML.
$mappings1 = $xml.supplementalData.windowsZones.mapTimezones.mapZone | select Type,Other 

# Extrapolate extra rows for entries that contain more than one IANA name seperated by spaces.
# Example: |<mapZone other="Alaskan Standard Time" territory="US" type="America/Anchorage America/Juneau America/Nome America/Sitka America/Yakutat"/>
$mappings2 = $mappings1 | %{
    $mapping = $_
    $_.Type.Split(" ") | %{
        New-Object PSObject -Property @{type = $_; other = $mapping.other}
    }  
}

# Remove dup's
$mappings3 = $mappings2 | sort type -Unique

# Generate the case statements.
$mappings3 | %{ [String]::Format("`"{1}`" {{`"{0}`"}}", $_.Type, $_.Other)}

I need the switch to return only one entry so I pruned that list down. Here’s the lookup script:

$CurrentTimeZone = Get-TimeZone

$tz = Switch -Wildcard ($CurrentTimeZone.id)
{ 
  "Afghanistan Standard Time"       { "Asia/Kabul" }
  "Alaskan Standard Time"           { "America/Anchorage" }
  "Aleutian Standard Time"          { "America/Adak" }
  "Altai Standard Time"             { "Asia/Barnaul" }
  "Arab Standard Time"              { "Asia/Bahrain" }
  "Arabian Standard Time"           { "Asia/Dubai" }
  "Arabic Standard Time"            { "Asia/Baghdad" }
  "Argentina Standard Time"         { "America/Buenos_Aires" }
  "Astrakhan Standard Time"         { "Europe/Astrakhan" }
  "Atlantic Standard Time"          { "America/Halifax" }
  "Atlantic Standard Time"          { "Atlantic/Bermuda" }
  "AUS Central Standard Time"       { "Australia/Darwin" }
  "Aus Central W. Standard Time"    { "Australia/Eucla" }
  "AUS Eastern Standard Time"       { "Australia/Sydney" }
  "Azerbaijan Standard Time"        { "Asia/Baku" }
  "Azores Standard Time"            { "Atlantic/Azores" }
  "Bahia Standard Time"             { "America/Bahia" }
  "Bangladesh Standard Time"        { "Asia/Dhaka" }
  "Belarus Standard Time"           { "Europe/Minsk" }
  "Bougainville Standard Time"      { "Pacific/Bougainville" }
  "Canada Central Standard Time"    { "America/Regina" }
  "Cape Verde Standard Time"        { "Atlantic/Cape_Verde" }
  "Caucasus Standard Time"          { "Asia/Yerevan" }
  "Cen. Australia Standard Time"    { "Australia/Adelaide" }
  "Central America Standard Time"   { "America/Costa_Rica" }
  "Central Asia Standard Time"      { "Asia/Bishkek" }
  "Central Brazilian Standard Time" { "America/Cuiaba" }
  "Central Europe Standard Time"    { "Europe/Prague" }
  "Central European Standard Time"  { "Europe/Warsaw" }
  "Central Pacific Standard Time"   { "Pacific/Guadalcanal" }
  "Central Standard Time (Mexico)"  { "America/Mexico_City" }
  "Central Standard Time"           { "America/Chicago" }
  "Chatham Islands Standard Time"   { "Pacific/Chatham" }
  "China Standard Time"             { "Asia/Hong_Kong" }
  "Cuba Standard Time"              { "America/Havana" }
  "Dateline Standard Time"          { "Etc/GMT+12" }
  "E. Africa Standard Time"         { "Africa/Nairobi" }
  "E. Australia Standard Time"      { "Australia/Brisbane" }
  "E. Europe Standard Time"         { "Europe/Chisinau" }
  "E. South America Standard Time"  { "America/Sao_Paulo" }
  "Easter Island Standard Time"     { "Pacific/Easter" }
  "Eastern Standard Time (Mexico)"  { "America/Cancun" }
  "Eastern Standard Time"           { "America/New_York" }
  "Egypt Standard Time"             { "Africa/Cairo" }
  "Ekaterinburg Standard Time"      { "Asia/Yekaterinburg" }
  "Fiji Standard Time"              { "Pacific/Fiji" }
  "FLE Standard Time"               { "Europe/Helsinki" }
  "Georgian Standard Time"          { "Asia/Tbilisi" }
  "GMT Standard Time"               { "Europe/London" }
  "Greenland Standard Time"         { "America/Godthab" }
  "Greenwich Standard Time"         { "Atlantic/Reykjavik" }
  "GTB Standard Time"               { "Europe/Athens" }
  "Haiti Standard Time"             { "America/Port-au-Prince" }
  "Hawaiian Standard Time"          { "Pacific/Honolulu" }
  "India Standard Time"             { "Asia/Calcutta" }
  "Iran Standard Time"              { "Asia/Tehran" }
  "Israel Standard Time"            { "Asia/Jerusalem" }
  "Jordan Standard Time"            { "Asia/Amman" }
  "Kaliningrad Standard Time"       { "Europe/Kaliningrad" }
  "Korea Standard Time"             { "Asia/Seoul" }
  "Libya Standard Time"             { "Africa/Tripoli" }
  "Line Islands Standard Time"      { "Pacific/Kiritimati" }
  "Lord Howe Standard Time"         { "Australia/Lord_Howe" }
  "Magadan Standard Time"           { "Asia/Magadan" }
  "Magallanes Standard Time"        { "America/Punta_Arenas" }
  "Marquesas Standard Time"         { "Pacific/Marquesas" }
  "Mauritius Standard Time"         { "Indian/Mauritius" }
  "Middle East Standard Time"       { "Asia/Beirut" }
  "Montevideo Standard Time"        { "America/Montevideo" }
  "Morocco Standard Time"           { "Africa/Casablanca" }
  "Mountain Standard Time (Mexico)" { "America/Mazatlan" }
  "Mountain Standard Time"          { "America/Denver" }
  "Myanmar Standard Time"           { "Asia/Rangoon" }
  "N. Central Asia Standard Time"   { "Asia/Novosibirsk" }
  "Namibia Standard Time"           { "Africa/Windhoek" }
  "Nepal Standard Time"             { "Asia/Katmandu" }
  "New Zealand Standard Time"       { "Pacific/Auckland" }
  "Newfoundland Standard Time"      { "America/St_Johns" }
  "Norfolk Standard Time"           { "Pacific/Norfolk" }
  "North Asia East Standard Time"   { "Asia/Irkutsk" }
  "North Asia Standard Time"        { "Asia/Krasnoyarsk" }
  "North Korea Standard Time"       { "Asia/Pyongyang" }
  "Omsk Standard Time"              { "Asia/Omsk" }
  "Pacific SA Standard Time"        { "America/Santiago" }
  "Pacific Standard Time (Mexico)"  { "America/Tijuana" }
  "Pacific Standard Time"           { "America/Los_Angeles" }
  "Pakistan Standard Time"          { "Asia/Karachi" }
  "Paraguay Standard Time"          { "America/Asuncion" }
  "Qyzylorda Standard Time"         { "Asia/Qyzylorda" }
  "Romance Standard Time"           { "Europe/Brussels" }
  "Russia Time Zone 10"             { "Asia/Srednekolymsk" }
  "Russia Time Zone 11"             { "Asia/Anadyr" }
  "Russia Time Zone 3"              { "Europe/Samara" }
  "Russian Standard Time"           { "Europe/Moscow" }
  "SA Eastern Standard Time"        { "America/Recife" }
  "SA Pacific Standard Time"        { "America/Bogota" }
  "SA Western Standard Time"        { "America/Puerto_Rico" }
  "Saint Pierre Standard Time"      { "America/Miquelon" }
  "Sakhalin Standard Time"          { "Asia/Sakhalin" }
  "Samoa Standard Time"             { "Pacific/Apia" }
  "Sao Tome Standard Time"          { "Africa/Sao_Tome" }
  "Saratov Standard Time"           { "Europe/Saratov" }
  "SE Asia Standard Time"           { "Asia/Bangkok" }
  "Singapore Standard Time"         { "Asia/Singapore" }
  "South Africa Standard Time"      { "Africa/Johannesburg" }
  "South Sudan Standard Time"       { "Africa/Juba" }
  "Sri Lanka Standard Time"         { "Asia/Colombo" }
  "Sudan Standard Time"             { "Africa/Khartoum" }
  "Syria Standard Time"             { "Asia/Damascus" }
  "Taipei Standard Time"            { "Asia/Taipei" }
  "Tasmania Standard Time"          { "Australia/Hobart" }
  "Tocantins Standard Time"         { "America/Araguaina" }
  "Tokyo Standard Time"             { "Asia/Tokyo" }
  "Tomsk Standard Time"             { "Asia/Tomsk" }
  "Tonga Standard Time"             { "Pacific/Tongatapu" }
  "Transbaikal Standard Time"       { "Asia/Chita" }
  "Turkey Standard Time"            { "Europe/Istanbul" }
  "Turks And Caicos Standard Time"  { "America/Grand_Turk" }
  "Ulaanbaatar Standard Time"       { "Asia/Ulaanbaatar" }
  "US Eastern Standard Time"        { "America/Indianapolis" }
  "US Mountain Standard Time"       { "America/Phoenix" }
  "UTC"                             { "Etc/UTC" }
  "UTC+12"                          { "Pacific/Funafuti" }
  "UTC+13"                          { "Pacific/Enderbury" }
  "UTC-02"                          { "Atlantic/South_Georgia" }
  "UTC-08"                          { "Pacific/Pitcairn" }
  "UTC-09"                          { "Pacific/Gambier" }
  "UTC-11"                          { "Pacific/Midway" }
  "Venezuela Standard Time"         { "America/Caracas" }
  "Vladivostok Standard Time"       { "Asia/Vladivostok" }
  "Volgograd Standard Time"         { "Europe/Volgograd" }
  "W. Australia Standard Time"      { "Australia/Perth" }
  "W. Central Africa Standard Time" { "Africa/Algiers" }
  "W. Europe Standard Time"         { "Europe/Berlin" }
  "W. Mongolia Standard Time"       { "Asia/Hovd" }
  "West Asia Standard Time"         { "Asia/Almaty" }
  "West Bank Standard Time"         { "Asia/Hebron" }
  "West Pacific Standard Time"      { "Pacific/Guam" }
  "Yakutsk Standard Time"           { "Asia/Yakutsk" }
  "Yukon Standard Time"             { "America/Whitehorse" }
}

write-host $CurrentTimeZone
write-host $tz

4

You can simplify your code significantly by using XPath to lookup mappings directly against the XML document:

$xPath = '//supplementalData/windowsZones/mapTimezones/mapZone[@other = "Bahia Standard Time"]'
$bahiaEntry = $xml.SelectSingleNode($xPath)
$bahiaEntry.Type   # resolves to `America/Bahia`

Wrapping this in a function is trivial, but you may want to additionally host the function in a module, like so:

New-Module -Name tzResolutionModule -ScriptBlock {
  function Resolve-WindowsTimeZoneId {
    param(
      [Parameter(ValueFromPipeline, ValueFromPipelineByPropertyName)]
      [Alias('Id')]
      [string]$TZIdentifier = $(Get-TimeZone |% Id))

    process {
      $xPathExpression = '//supplementalData/windowsZones/mapTimezones/mapZone[@other = "{0}"]' -f $TZIdentifier
      $mapZoneEntry = $script:_timeZoneMap.SelectSingleNode($xPathExpression)

      if (-not $mapZoneEntry){
        throw "Unable to resolve time zone label '${TZIdentifier}'"
      }
      else {
        # we found at least one entry, output the first corresponding IANA identifier
        return -split $mapZoneEntry.Type |Select-Object -First 1
      }
    }
  }

  $_timeZoneMap = Invoke-RestMethod -Uri https://github.com/unicode-org/cldr/raw/main/common/supplemental/windowsZones.xml
} |Import-Module -Force

Wrapping the Resolve-WindowsTimeZoneId in a module allows us to take advantage of module-scoped variables for persistent storage – in this case to ensure we only download the zone mapping document once, on module import.

Now you can do:

PS ~> Resolve-WindowsTimeZoneId 'Central Standard Time'
America/Chicago

And get a near-instant response – but thanks to the [Parameter(...)] and [Alias(...)] decorators on the function parameter, you can now also do:

Get-TimeZone |Resolve-WindowsTimeZoneId
# or
'Central Standard Time' |Resolve-WindowsTimeZoneId

3

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật