Last active
February 27, 2022 15:15
-
-
Save CMCDragonkai/a53df086cce25319d7530eb4b2ca1da9 to your computer and use it in GitHub Desktop.
CLI: Convert Windows CLDR Timezone to IANA Timezone Identifiers
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
if [[ "$@" == "" || "$@" == *-h* || "$@" == *--help* ]]; then | |
cat<<EOF | |
tz-windows-to-iana - Convert Windows timezone CLDR to IANA Identifiers. | |
You can acquire Windows timezone CLDR by using the CMD tool \`tzutil\`. | |
There are 2 protocols for identifying timezones. | |
There is the IANA timezone database: https://en.wikipedia.org/wiki/Tz_database | |
There is the Unicode Common Locale Data Repository: http://cldr.unicode.org/ | |
This just utilises some databases to map Unicode CLDR to IANA timezones. | |
The mapping isn't completely bidirectional. But we make a best choice possible. | |
We used data from https://github.com/nodatime/nodatime/blob/master/data/cldr/ | |
and https://en.wikipedia.org/wiki/List_of_tz_database_time_zones | |
Timezone information changes over time, so this data can require updating. | |
Usage: | |
tz-windows-to-iana ["unicode-cldr"] | |
tz-windows-to-iana -h | --help | |
Options: | |
-h --help Show this help text. | |
EOF | |
exit 0 | |
fi | |
# 3 improvements can be made: | |
# First: | |
# The mapping IANA -> Windows Unicode CLDR is actually theoretically surjective, but in practice it is non-injective and non-surjective. | |
# Theoretically, 1 IANA is mapped to 1 Windows Unicode CLDR, but 1 Windows Unicode CLDR is mapped to one or more IANA. | |
# In practice, some IANA cannot be mapped and some Windows Unicode CLDR cannot be mapped, and this requires constant updating. | |
# To do this we would need to use null `\0` delimited values for the values of Windows Unicode CLDR keys. | |
# Queries can pipe results to `cut -d '' -fX` to acquire whichever value is necessary. | |
# Second: | |
# We could make this data structure bidirectional, to allow IANA to Windows Unicode CLDR conversions. | |
# The keys of IANA is uniquely different from Windows Unicode CLDR, so we can just add those as keys. | |
# However this is a lot of work. | |
# Third: | |
# Some way of automatically processing new revisions of tzdata and nodatime. | |
declare -A windows_to_iana | |
windows_to_iana["(UTC-12:00) International Date Line West"]="Etc/GMT+12" | |
windows_to_iana["(UTC-11:00) Coordinated Universal Time-11"]="Etc/GMT+11" | |
windows_to_iana["(UTC-10:00) Hawaii"]="Pacific/Honolulu" | |
windows_to_iana["(UTC-09:30) Marquesas Islands"]="Pacific/Marquesas" | |
windows_to_iana["(UTC-09:00) Alaska"]="America/Anchorage" | |
windows_to_iana["(UTC-09:00) Co-ordinated Universal Time-09"]="Etc/GMT+9" | |
windows_to_iana["(UTC-08:00) Baja California"]="America/Tijuana" | |
windows_to_iana["(UTC-08:00) Co-ordinated Universal Time-08"]="Etc/GMT+8" | |
windows_to_iana["(UTC-08:00) Pacific Time (US & Canada)"]="America/Los_Angeles" | |
windows_to_iana["(UTC-07:00) Arizona"]="America/Phoenix" | |
windows_to_iana["(UTC-07:00) Chihuahua, La Paz, Mazatlan"]="America/Chihuahua" | |
windows_to_iana["(UTC-07:00) Mountain Time (US & Canada)"]="America/Denver" | |
windows_to_iana["(UTC-06:00) Central America"]="America/Guatemala" | |
windows_to_iana["(UTC-06:00) Central Time (US & Canada)"]="America/Chicago" | |
windows_to_iana["(UTC-06:00) Easter Island"]="Pacific/Easter" | |
windows_to_iana["(UTC-06:00) Guadalajara, Mexico City, Monterrey"]="America/Mexico_City" | |
windows_to_iana["(UTC-06:00) Saskatchewan"]="America/Regina" | |
windows_to_iana["(UTC-05:00) Bogota, Lima, Quito, Rio Branco"]="America/Bogota" | |
windows_to_iana["(UTC-05:00) Chetumal"]="America/Cancun" | |
windows_to_iana["(UTC-05:00) Eastern Time (US & Canada)"]="America/New_York" | |
windows_to_iana["(UTC-05:00) Haiti"]="America/Port-au-Prince" | |
windows_to_iana["(UTC-05:00) Havana"]="America/Havana" | |
windows_to_iana["(UTC-05:00) Indiana (East)"]="America/Indianapolis" | |
windows_to_iana["(UTC-04:00) Asuncion"]="America/Asuncion" | |
windows_to_iana["(UTC-04:00) Atlantic Time (Canada)"]="America/Halifax" | |
windows_to_iana["(UTC-04:00) Caracas"]="America/Caracas" | |
windows_to_iana["(UTC-04:00) Cuiaba"]="America/Cuiaba" | |
windows_to_iana["(UTC-04:00) Georgetown, La Paz, Manaus, San Juan"]="America/La_Paz" | |
windows_to_iana["(UTC-04:00) Santiago"]="America/Santiago" | |
windows_to_iana["(UTC-04:00) Turks and Caicos"]="America/Grand_Turk" | |
windows_to_iana["(UTC-03:30) Newfoundland"]="America/St_Johns" | |
windows_to_iana["(UTC-03:00) Araguaina"]="America/Araguaina" | |
windows_to_iana["(UTC-03:00) Brasilia"]="America/Sao_Paulo" | |
windows_to_iana["(UTC-03:00) Cayenne, Fortaleza"]="America/Cayenne" | |
windows_to_iana["(UTC-03:00) City of Buenos Aires"]="America/Buenos_Aires" | |
windows_to_iana["(UTC-03:00) Greenland"]="America/Godthab" | |
windows_to_iana["(UTC-03:00) Montevideo"]="America/Montevideo" | |
windows_to_iana["(UTC-03:00) Saint Pierre and Miquelon"]="America/Miquelon" | |
windows_to_iana["(UTC-03:00) Salvador"]="America/Bahia" | |
windows_to_iana["(UTC-02:00) Co-ordinated Universal Time-02"]="Etc/GMT+2" | |
windows_to_iana["(UTC-01:00) Azores"]="Atlantic/Azores" | |
windows_to_iana["(UTC-01:00) Cabo Verde Is."]="Atlantic/Cape_Verde" | |
windows_to_iana["(UTC) Co-ordinated Universal Time"]="Etc/GMT" | |
windows_to_iana["(UTC+00:00) Casablanca"]="Africa/Casablanca" | |
windows_to_iana["(UTC+00:00) Dublin, Edinburgh, Lisbon, London"]="Europe/London" | |
windows_to_iana["(UTC+00:00) Monrovia, Reykjavik"]="Atlantic/Reykjavik" | |
windows_to_iana["(UTC+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"]="Europe/Berlin" | |
windows_to_iana["(UTC+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague"]="Europe/Budapest" | |
windows_to_iana["(UTC+01:00) Brussels, Copenhagen, Madrid, Paris"]="Europe/Paris" | |
windows_to_iana["(UTC+01:00) Sarajevo, Skopje, Warsaw, Zagreb"]="Europe/Warsaw" | |
windows_to_iana["(UTC+01:00) West Central Africa"]="Africa/Lagos" | |
windows_to_iana["(UTC+01:00) Windhoek"]="Africa/Windhoek" | |
windows_to_iana["(UTC+02:00) Amman"]="Asia/Amman" | |
windows_to_iana["(UTC+02:00) Athens, Bucharest"]="Europe/Bucharest" | |
windows_to_iana["(UTC+02:00) Beirut"]="Asia/Beirut" | |
windows_to_iana["(UTC+02:00) Cairo"]="Africa/Cairo" | |
windows_to_iana["(UTC+02:00) Chisinau"]="Europe/Chisinau" | |
windows_to_iana["(UTC+02:00) Damascus"]="Asia/Damascus" | |
windows_to_iana["(UTC+02:00) Gaza, Hebron"]="Asia/Gaza" | |
windows_to_iana["(UTC+02:00) Harare, Pretoria"]="Africa/Johannesburg" | |
windows_to_iana["(UTC+02:00) Helsinki, Kyiv, Riga, Sofia, Tallinn, Vilnius"]="Europe/Kiev" | |
windows_to_iana["(UTC+02:00) Istanbul"]="Europe/Istanbul" | |
windows_to_iana["(UTC+02:00) Jerusalem"]="Asia/Jerusalem" | |
windows_to_iana["(UTC+02:00) Kaliningrad"]="Europe/Kaliningrad" | |
windows_to_iana["(UTC+02:00) Tripoli"]="Africa/Tripoli" | |
windows_to_iana["(UTC+03:00) Baghdad"]="Asia/Baghdad" | |
windows_to_iana["(UTC+03:00) Kuwait, Riyadh"]="Asia/Riyadh" | |
windows_to_iana["(UTC+03:00) Minsk"]="Europe/Minsk" | |
windows_to_iana["(UTC+03:00) Moscow, St. Petersburg, Volgograd"]="Europe/Moscow" | |
windows_to_iana["(UTC+03:00) Nairobi"]="Africa/Nairobi" | |
windows_to_iana["(UTC+03:30) Tehran"]="Asia/Tehran" | |
windows_to_iana["(UTC+04:00) Abu Dhabi, Muscat"]="Asia/Dubai" | |
windows_to_iana["(UTC+04:00) Astrakhan, Ulyanovsk"]="Europe/Samara" | |
windows_to_iana["(UTC+04:00) Baku"]="Asia/Baku" | |
windows_to_iana["(UTC+04:00) Izhevsk, Samara"]="Europe/Samara" | |
windows_to_iana["(UTC+04:00) Port Louis"]="Indian/Mauritius" | |
windows_to_iana["(UTC+04:00) Tbilisi"]="Asia/Tbilisi" | |
windows_to_iana["(UTC+04:00) Yerevan"]="Asia/Yerevan" | |
windows_to_iana["(UTC+04:30) Kabul"]="Asia/Kabul" | |
windows_to_iana["(UTC+05:00) Ashgabat, Tashkent"]="Asia/Tashkent" | |
windows_to_iana["(UTC+05:00) Ekaterinburg"]="Asia/Yekaterinburg" | |
windows_to_iana["(UTC+05:00) Islamabad, Karachi"]="Asia/Karachi" | |
windows_to_iana["(UTC+05:30) Chennai, Kolkata, Mumbai, New Delhi"]="Asia/Calcutta" | |
windows_to_iana["(UTC+05:30) Sri Jayawardenepura"]="Asia/Colombo" | |
windows_to_iana["(UTC+05:45) Kathmandu"]="Asia/Kathmandu" | |
windows_to_iana["(UTC+06:00) Astana"]="Asia/Almaty" | |
windows_to_iana["(UTC+06:00) Dhaka"]="Asia/Dhaka" | |
windows_to_iana["(UTC+06:00) Novosibirsk"]="Asia/Novosibirsk" | |
windows_to_iana["(UTC+06:30) Yangon (Rangoon)"]="Asia/Rangoon" | |
windows_to_iana["(UTC+07:00) Bangkok, Hanoi, Jakarta"]="Asia/Bangkok" | |
windows_to_iana["(UTC+07:00) Barnaul, Gorno-Altaysk"]="Asia/Krasnoyarsk" | |
windows_to_iana["(UTC+07:00) Hovd"]="Asia/Hovd" | |
windows_to_iana["(UTC+07:00) Krasnoyarsk"]="Asia/Krasnoyarsk" | |
windows_to_iana["(UTC+07:00) Tomsk"]="Asia/Tomsk" | |
windows_to_iana["(UTC+08:00) Beijing, Chongqing, Hong Kong SAR, Urumqi"]="Asia/Shanghai" | |
windows_to_iana["(UTC+08:00) Irkutsk"]="Asia/Irkutsk" | |
windows_to_iana["(UTC+08:00) Kuala Lumpur, Singapore"]="Asia/Singapore" | |
windows_to_iana["(UTC+08:00) Perth"]="Australia/Perth" | |
windows_to_iana["(UTC+08:00) Taipei"]="Asia/Taipei" | |
windows_to_iana["(UTC+08:00) Ulaanbaatar"]="Asia/Ulaanbaatar" | |
windows_to_iana["(UTC+08:30) Pyongyang"]="Asia/Pyongyang" | |
windows_to_iana["(UTC+08:45) Eucla"]="Australia/Eucla" | |
windows_to_iana["(UTC+09:00) Chita"]="Asia/Chita" | |
windows_to_iana["(UTC+09:00) Osaka, Sapporo, Tokyo"]="Asia/Tokyo" | |
windows_to_iana["(UTC+09:00) Seoul"]="Asia/Seoul" | |
windows_to_iana["(UTC+09:00) Yakutsk"]="Asia/Yakutsk" | |
windows_to_iana["(UTC+09:30) Adelaide"]="Australia/Adelaide" | |
windows_to_iana["(UTC+09:30) Darwin"]="Australia/Darwin" | |
windows_to_iana["(UTC+10:00) Brisbane"]="Australia/Brisbane" | |
windows_to_iana["(UTC+10:00) Canberra, Melbourne, Sydney"]="Australia/Sydney" | |
windows_to_iana["(UTC+10:00) Guam, Port Moresby"]="Pacific/Port_Moresby" | |
windows_to_iana["(UTC+10:00) Hobart"]="Australia/Hobart" | |
windows_to_iana["(UTC+10:00) Vladivostok"]="Asia/Vladivostok" | |
windows_to_iana["(UTC+10:30) Lord Howe Island"]="Australia/Lord_Howe" | |
windows_to_iana["(UTC+11:00) Bougainville Island"]="Pacific/Bougainville" | |
windows_to_iana["(UTC+11:00) Chokurdakh"]="Asia/Srednekolymsk" | |
windows_to_iana["(UTC+11:00) Magadan"]="Asia/Magadan" | |
windows_to_iana["(UTC+11:00) Norfolk Island"]="Pacific/Norfolk" | |
windows_to_iana["(UTC+11:00) Sakhalin"]="Asia/Sakhalin" | |
windows_to_iana["(UTC+11:00) Solomon Is., New Caledonia"]="Pacific/Guadalcanal" | |
windows_to_iana["(UTC+12:00) Anadyr, Petropavlovsk-Kamchatsky"]="Asia/Kamchatka" | |
windows_to_iana["(UTC+12:00) Auckland, Wellington"]="Pacific/Auckland" | |
windows_to_iana["(UTC+12:00) Co-ordinated Universal Time+12"]="Etc/GMT-12" | |
windows_to_iana["(UTC+12:00) Fiji"]="Pacific/Fiji" | |
windows_to_iana["(UTC+12:45) Chatham Islands"]="Pacific/Chatham" | |
windows_to_iana["(UTC+13:00) Nuku'alofa"]="Pacific/Tongatapu" | |
windows_to_iana["(UTC+13:00) Samoa"]="Pacific/Apia" | |
windows_to_iana["(UTC+14:00) Kiritimati Island"]="Pacific/Kiritimati" | |
trimlr () { | |
# Determine if 'extglob' is currently on. | |
local extglobWasOff=1 | |
shopt extglob >/dev/null && extglobWasOff=0 | |
# Turn 'extglob' on, if currently turned off. | |
(( extglobWasOff )) && shopt -s extglob | |
# Trim leading and trailing whitespace | |
local var=$1 | |
var=${var##+([[:space:]])} | |
var=${var%%+([[:space:]])} | |
# If 'extglob' was off before, turn it back off. | |
(( extglobWasOff )) && shopt -u extglob | |
printf "%s" "$var" | |
} | |
windows_cldr="$(trimlr "$1")" | |
result="${windows_to_iana["$windows_cldr"]}" | |
if [ -z "$result" ]; then | |
exit 1 | |
else | |
printf "%s\n" "$result" | |
fi |
Great job!
May I ask is this published under MIT license?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Nice! How about non-CLDR Windows timezone ids as in http://unicode.org/repos/cldr/trunk/common/supplemental/windowsZones.xml?