Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[libs][Unix][perf] Lazily initialize TimeZoneInfo names and order GetSystemTimeZones by Ids #88368

Merged
merged 17 commits into from
Jul 10, 2023

Conversation

mdh1418
Copy link
Member

@mdh1418 mdh1418 commented Jul 4, 2023

Fixes dotnet/android#8050

The TimeZoneInfo(byte[] data, string id, bool dstDisabled) constructor on Unix sets internal fields used in DisplayName, StandardName, and DaylightName by querying the timezone database via TryPopulateTimeZoneDisplayNamesFromGlobalizationData. For APIs that invoke that constructor for every timezone (>400 timezones on Android) like GetSystemTimeZones() this operation is costly.
On average (on my machine, Mac mini M1, 2020 with 16GB memory running on OS 13.4 using Android Studio Emulator), TryPopulateTimeZoneDisplayNamesFromGlobalizationData takes ~66% (719.31ms) of the time GetSystemTimeZones takes (~1.091s). More specifically, GetFullValueForDisplayNameField takes ~93% (669ms) of the time of TryPopulateTimeZoneDisplayNamesFromGlobalizationData, with the Interop GetDisplayName.

Example timing breakdown

A breakdown of the `630.37ms` it took to get `GetFullValueForDisplayNameField` is
`336.975ms` `GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.Generic, uiCulture.Name, ref genericName);` 
`107.929ms` `GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.GenericLocation, uiCulture.Name, ref genericLocationName);`
`1.6074ms`  `GetDisplayName(GmtId, Interop.Globalization.TimeZoneDisplayNameType.GenericLocation, uiCulture.Name, ref gmtLocationName);`
`54.2908ms` `GetDisplayName(GmtId, Interop.Globalization.TimeZoneDisplayNameType.Generic, uiCulture.Name, ref gmtGenericName);`
`1.1826ms` `StringArrayContains(timeZoneId, s_ZonesThatUseLocationName, StringComparison.OrdinalIgnoreCase)`
`17.178ms` `GetExemplarCityName(timeZoneId, uiCulture.Name);`
`75.2069ms` `uiCulture.CompareInfo.IndexOf(genericName, exemplarCityName, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0 && genericLocationName != null`

This PR looks to improve the performance of APIs invoking a large number of TimeZoneInfo constructors by:

  1. Lazily loading the values for DisplayName, StandardName, and DaylightName
  2. Ordering timezones by Id in GetSystemTimeZones() to avoid perf hit from DisplayName call.
  3. Direct numerical comparison for known UTC alias to reduce number of calls to String.Equals

On average (on my machine, Mac mini M1, 2020 with 16GB memory running on OS 13.4 using Android Studio Emulator),
Timing TimeZoneInfo.GetSystemTimeZones() with the changes in this PR when sorting based on DisplayName:
GetSystemTimeZones: ~677ms
TimeZoneInfo(byte[] data, string id, bool dstDisabled): ~115.92ms

@ghost
Copy link

ghost commented Jul 4, 2023

Tagging subscribers to this area: @dotnet/area-system-datetime
See info in area-owners.md if you want to be subscribed.

Issue Details

Fixes dotnet/android#8050

The TimeZoneInfo(byte[] data, string id, bool dstDisabled) constructor on Unix sets internal fields used in DisplayName, StandardName, and DaylightName by querying the timezone database via TryPopulateTimeZoneDisplayNamesFromGlobalizationData. For APIs that invoke that constructor for every timezone (>400 timezones on Android) like GetSystemTimeZones() this operation is costly.
On average (on my machine, Mac mini M1, 2020 with 16GB memory running on OS 13.4 using Android Studio Emulator), TryPopulateTimeZoneDisplayNamesFromGlobalizationData takes ~66% (719.31ms) of the time GetSystemTimeZones takes (~1.091s). More specifically, GetFullValueForDisplayNameField takes ~93% (669ms) of the time of TryPopulateTimeZoneDisplayNamesFromGlobalizationData, with the Interop GetDisplayName.

Example timing breakdown

A breakdown of the `630.37ms` it took to get `GetFullValueForDisplayNameField` is
`336.975ms` `GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.Generic, uiCulture.Name, ref genericName);` 
`107.929ms` `GetDisplayName(timeZoneId, Interop.Globalization.TimeZoneDisplayNameType.GenericLocation, uiCulture.Name, ref genericLocationName);`
`1.6074ms`  `GetDisplayName(GmtId, Interop.Globalization.TimeZoneDisplayNameType.GenericLocation, uiCulture.Name, ref gmtLocationName);`
`54.2908ms` `GetDisplayName(GmtId, Interop.Globalization.TimeZoneDisplayNameType.Generic, uiCulture.Name, ref gmtGenericName);`
`1.1826ms` `StringArrayContains(timeZoneId, s_ZonesThatUseLocationName, StringComparison.OrdinalIgnoreCase)`
`17.178ms` `GetExemplarCityName(timeZoneId, uiCulture.Name);`
`75.2069ms` `uiCulture.CompareInfo.IndexOf(genericName, exemplarCityName, CompareOptions.IgnoreCase | CompareOptions.IgnoreNonSpace) >= 0 && genericLocationName != null`

This PR looks to improve the performance of APIs invoking a large number of TimeZoneInfo constructors by:

  1. Lazily loading the values for DisplayName, StandardName, and DaylightName
  2. Ordering timezones by Id in GetSystemTimeZones() to avoid perf hit from DisplayName call.
  3. Direct numerical comparison for known UTC alias to reduce number of calls to String.Equals

On average (on my machine, Mac mini M1, 2020 with 16GB memory running on OS 13.4 using Android Studio Emulator),
Timing TimeZoneInfo.GetSystemTimeZones() with the changes in this PR:
GetSystemTimeZones: ~145ms
TimeZoneInfo(byte[] data, string id, bool dstDisabled): ~77.71ms


GetSystemTimeZones Ordering

Before

(click to expand)
Id Display Name
Pacific/Niue (UTC-11:00) Niue Time
Pacific/Midway (UTC-11:00) Samoa Standard Time (Midway)
Pacific/Pago_Pago (UTC-11:00) Samoa Standard Time (Pago Pago)
Pacific/Rarotonga (UTC-10:00) Cook Islands Standard Time (Rarotonga)
America/Adak (UTC-10:00) Hawaii-Aleutian Time (Adak)
Pacific/Honolulu (UTC-10:00) Hawaii-Aleutian Time (Adak) (Honolulu)
Pacific/Tahiti (UTC-10:00) Tahiti Time
Pacific/Marquesas (UTC-09:30) Marquesas Time
America/Anchorage (UTC-09:00) Alaska Time (Anchorage)
America/Juneau (UTC-09:00) Alaska Time (Juneau)
America/Metlakatla (UTC-09:00) Alaska Time (Metlakatla)
America/Nome (UTC-09:00) Alaska Time (Nome)
America/Sitka (UTC-09:00) Alaska Time (Sitka)
America/Yakutat (UTC-09:00) Alaska Time (Yakutat)
Pacific/Gambier (UTC-09:00) Gambier Time
America/Los_Angeles (UTC-08:00) Pacific Time (Los Angeles)
America/Tijuana (UTC-08:00) Pacific Time (Tijuana)
America/Vancouver (UTC-08:00) Pacific Time (Vancouver)
Pacific/Pitcairn (UTC-08:00) Pitcairn Islands Time
America/Chihuahua (UTC-07:00) Mexican Pacific Time (Chihuahua)
America/Hermosillo (UTC-07:00) Mexican Pacific Time (Hermosillo)
America/Mazatlan (UTC-07:00) Mexican Pacific Time (Mazatlan)
America/Boise (UTC-07:00) Mountain Time (Boise)
America/Cambridge_Bay (UTC-07:00) Mountain Time (Cambridge Bay)
America/Creston (UTC-07:00) Mountain Time (Creston)
America/Dawson_Creek (UTC-07:00) Mountain Time (Dawson Creek)
America/Denver (UTC-07:00) Mountain Time (Denver)
America/Edmonton (UTC-07:00) Mountain Time (Edmonton)
America/Fort_Nelson (UTC-07:00) Mountain Time (Fort Nelson)
America/Inuvik (UTC-07:00) Mountain Time (Inuvik)
America/Ojinaga (UTC-07:00) Mountain Time (Ojinaga)
America/Phoenix (UTC-07:00) Mountain Time (Phoenix)
America/Yellowknife (UTC-07:00) Mountain Time (Yellowknife)
America/Dawson (UTC-07:00) Yukon Time (Dawson)
America/Whitehorse (UTC-07:00) Yukon Time (Whitehorse)
America/Bahia_Banderas (UTC-06:00) Central Time (Bahia Banderas)
America/Belize (UTC-06:00) Central Time (Belize)
America/North_Dakota/Beulah (UTC-06:00) Central Time (Beulah, North Dakota)
America/North_Dakota/Center (UTC-06:00) Central Time (Center, North Dakota)
America/Chicago (UTC-06:00) Central Time (Chicago)
America/Costa_Rica (UTC-06:00) Central Time (Costa Rica)
America/El_Salvador (UTC-06:00) Central Time (El Salvador)
America/Guatemala (UTC-06:00) Central Time (Guatemala)
America/Indiana/Knox (UTC-06:00) Central Time (Knox, Indiana)
America/Managua (UTC-06:00) Central Time (Managua)
America/Matamoros (UTC-06:00) Central Time (Matamoros)
America/Menominee (UTC-06:00) Central Time (Menominee)
America/Merida (UTC-06:00) Central Time (Merida)
America/Mexico_City (UTC-06:00) Central Time (Mexico City)
America/Monterrey (UTC-06:00) Central Time (Monterrey)
America/North_Dakota/New_Salem (UTC-06:00) Central Time (New Salem, North Dakota)
America/Rainy_River (UTC-06:00) Central Time (Rainy River)
America/Rankin_Inlet (UTC-06:00) Central Time (Rankin Inlet)
America/Regina (UTC-06:00) Central Time (Regina)
America/Resolute (UTC-06:00) Central Time (Resolute)
America/Swift_Current (UTC-06:00) Central Time (Swift Current)
America/Tegucigalpa (UTC-06:00) Central Time (Tegucigalpa)
America/Indiana/Tell_City (UTC-06:00) Central Time (Tell City, Indiana)
America/Winnipeg (UTC-06:00) Central Time (Winnipeg)
Pacific/Easter (UTC-06:00) Easter Island Time
Pacific/Galapagos (UTC-06:00) Galapagos Time
America/Eirunepe (UTC-05:00) Acre Standard Time (Eirunepe)
America/Rio_Branco (UTC-05:00) Acre Standard Time (Rio Branco)
America/Bogota (UTC-05:00) Colombia Standard Time (Bogota)
America/Havana (UTC-05:00) Cuba Time
America/Atikokan (UTC-05:00) Eastern Time (Atikokan)
America/Cancun (UTC-05:00) Eastern Time (Cancun)
America/Cayman (UTC-05:00) Eastern Time (Cayman)
America/Detroit (UTC-05:00) Eastern Time (Detroit)
America/Grand_Turk (UTC-05:00) Eastern Time (Grand Turk)
America/Indiana/Indianapolis (UTC-05:00) Eastern Time (Indianapolis)
America/Iqaluit (UTC-05:00) Eastern Time (Iqaluit)
America/Jamaica (UTC-05:00) Eastern Time (Jamaica)
America/Kentucky/Louisville (UTC-05:00) Eastern Time (Louisville)
America/Indiana/Marengo (UTC-05:00) Eastern Time (Marengo, Indiana)
America/Kentucky/Monticello (UTC-05:00) Eastern Time (Monticello, Kentucky)
America/Nassau (UTC-05:00) Eastern Time (Nassau)
America/New_York (UTC-05:00) Eastern Time (New York)
America/Nipigon (UTC-05:00) Eastern Time (Nipigon)
America/Panama (UTC-05:00) Eastern Time (Panama)
America/Pangnirtung (UTC-05:00) Eastern Time (Pangnirtung)
America/Indiana/Petersburg (UTC-05:00) Eastern Time (Petersburg, Indiana)
America/Port-au-Prince (UTC-05:00) Eastern Time (Port-au-Prince)
America/Thunder_Bay (UTC-05:00) Eastern Time (Thunder Bay)
America/Toronto (UTC-05:00) Eastern Time (Toronto)
America/Indiana/Vevay (UTC-05:00) Eastern Time (Vevay, Indiana)
America/Indiana/Vincennes (UTC-05:00) Eastern Time (Vincennes, Indiana)
America/Indiana/Winamac (UTC-05:00) Eastern Time (Winamac, Indiana)
America/Guayaquil (UTC-05:00) Ecuador Time
America/Lima (UTC-05:00) Peru Standard Time (Lima)
America/Boa_Vista (UTC-04:00) Amazon Standard Time (Boa Vista)
America/Campo_Grande (UTC-04:00) Amazon Standard Time (Campo Grande)
America/Cuiaba (UTC-04:00) Amazon Standard Time (Cuiaba)
America/Manaus (UTC-04:00) Amazon Standard Time (Manaus)
America/Porto_Velho (UTC-04:00) Amazon Standard Time (Porto Velho)
America/Anguilla (UTC-04:00) Atlantic Time (Anguilla)
America/Antigua (UTC-04:00) Atlantic Time (Antigua)
America/Aruba (UTC-04:00) Atlantic Time (Aruba)
America/Barbados (UTC-04:00) Atlantic Time (Barbados)
Atlantic/Bermuda (UTC-04:00) Atlantic Time (Bermuda)
America/Blanc-Sablon (UTC-04:00) Atlantic Time (Blanc-Sablon)
America/Curacao (UTC-04:00) Atlantic Time (Curaçao)
America/Dominica (UTC-04:00) Atlantic Time (Dominica)
America/Glace_Bay (UTC-04:00) Atlantic Time (Glace Bay)
America/Goose_Bay (UTC-04:00) Atlantic Time (Goose Bay)
America/Grenada (UTC-04:00) Atlantic Time (Grenada)
America/Guadeloupe (UTC-04:00) Atlantic Time (Guadeloupe)
America/Halifax (UTC-04:00) Atlantic Time (Halifax)
America/Kralendijk (UTC-04:00) Atlantic Time (Kralendijk)
America/Lower_Princes (UTC-04:00) Atlantic Time (Lower Prince’s Quarter)
America/Marigot (UTC-04:00) Atlantic Time (Marigot)
America/Martinique (UTC-04:00) Atlantic Time (Martinique)
America/Moncton (UTC-04:00) Atlantic Time (Moncton)
America/Montserrat (UTC-04:00) Atlantic Time (Montserrat)
America/Port_of_Spain (UTC-04:00) Atlantic Time (Port of Spain)
America/Puerto_Rico (UTC-04:00) Atlantic Time (Puerto Rico)
America/Santo_Domingo (UTC-04:00) Atlantic Time (Santo Domingo)
America/St_Barthelemy (UTC-04:00) Atlantic Time (St. Barthélemy)
America/St_Kitts (UTC-04:00) Atlantic Time (St. Kitts)
America/St_Lucia (UTC-04:00) Atlantic Time (St. Lucia)
America/St_Thomas (UTC-04:00) Atlantic Time (St. Thomas)
America/St_Vincent (UTC-04:00) Atlantic Time (St. Vincent)
America/Thule (UTC-04:00) Atlantic Time (Thule)
America/Tortola (UTC-04:00) Atlantic Time (Tortola)
America/La_Paz (UTC-04:00) Bolivia Time
America/Santiago (UTC-04:00) Chile Time
America/Guyana (UTC-04:00) Guyana Time
America/Asuncion (UTC-04:00) Paraguay Time
America/Caracas (UTC-04:00) Venezuela Time
America/St_Johns (UTC-03:30) Newfoundland Time (St. John’s)
America/Argentina/Buenos_Aires (UTC-03:00) Argentina Standard Time (Buenos Aires)
America/Argentina/Catamarca (UTC-03:00) Argentina Standard Time (Catamarca)
America/Argentina/Cordoba (UTC-03:00) Argentina Standard Time (Cordoba)
America/Argentina/Jujuy (UTC-03:00) Argentina Standard Time (Jujuy)
America/Argentina/La_Rioja (UTC-03:00) Argentina Standard Time (La Rioja)
America/Argentina/Mendoza (UTC-03:00) Argentina Standard Time (Mendoza)
America/Argentina/Rio_Gallegos (UTC-03:00) Argentina Standard Time (Rio Gallegos)
America/Argentina/Salta (UTC-03:00) Argentina Standard Time (Salta)
America/Argentina/San_Juan (UTC-03:00) Argentina Standard Time (San Juan)
America/Argentina/San_Luis (UTC-03:00) Argentina Standard Time (San Luis)
America/Argentina/Tucuman (UTC-03:00) Argentina Standard Time (Tucuman)
America/Argentina/Ushuaia (UTC-03:00) Argentina Standard Time (Ushuaia)
America/Araguaina (UTC-03:00) Brasilia Standard Time (Araguaina)
America/Bahia (UTC-03:00) Brasilia Standard Time (Bahia)
America/Belem (UTC-03:00) Brasilia Standard Time (Belem)
America/Fortaleza (UTC-03:00) Brasilia Standard Time (Fortaleza)
America/Maceio (UTC-03:00) Brasilia Standard Time (Maceio)
America/Recife (UTC-03:00) Brasilia Standard Time (Recife)
America/Santarem (UTC-03:00) Brasilia Standard Time (Santarem)
America/Sao_Paulo (UTC-03:00) Brasilia Standard Time (Sao Paulo)
Atlantic/Stanley (UTC-03:00) Falkland Islands Standard Time (Stanley)
America/Cayenne (UTC-03:00) French Guiana Time
Antarctica/Palmer (UTC-03:00) Palmer Time
America/Punta_Arenas (UTC-03:00) Punta Arenas Time
Antarctica/Rothera (UTC-03:00) Rothera Time
America/Miquelon (UTC-03:00) St. Pierre & Miquelon Time
America/Paramaribo (UTC-03:00) Suriname Time
America/Montevideo (UTC-03:00) Uruguay Standard Time (Montevideo)
America/Nuuk (UTC-03:00) West Greenland Time (Nuuk)
America/Noronha (UTC-02:00) Fernando de Noronha Standard Time
Atlantic/South_Georgia (UTC-02:00) South Georgia Time
Atlantic/Azores (UTC-01:00) Azores Time
Atlantic/Cape_Verde (UTC-01:00) Cape Verde Standard Time
America/Scoresbysund (UTC-01:00) East Greenland Time (Ittoqqortoormiit)
UTC (UTC) Coordinated Universal Time
Africa/Ouagadougou (UTC+00:00) Burkina Faso Time
Africa/Abidjan (UTC+00:00) Côte d’Ivoire Time
America/Danmarkshavn (UTC+00:00) Danmarkshavn Time
Africa/Banjul (UTC+00:00) Gambia Time
Africa/Accra (UTC+00:00) Ghana Time
Europe/Guernsey (UTC+00:00) Guernsey Time
Africa/Conakry (UTC+00:00) Guinea Time
Africa/Bissau (UTC+00:00) Guinea-Bissau Time
Atlantic/Reykjavik (UTC+00:00) Iceland Time
Europe/Dublin (UTC+00:00) Ireland Time
Europe/Isle_of_Man (UTC+00:00) Isle of Man Time
Europe/Jersey (UTC+00:00) Jersey Time
Africa/Monrovia (UTC+00:00) Liberia Time
Africa/Bamako (UTC+00:00) Mali Time
Africa/Nouakchott (UTC+00:00) Mauritania Time
Africa/Casablanca (UTC+00:00) Morocco Time
Africa/Dakar (UTC+00:00) Senegal Time
Africa/Freetown (UTC+00:00) Sierra Leone Time
Atlantic/St_Helena (UTC+00:00) St. Helena Time
Africa/Sao_Tome (UTC+00:00) São Tomé & Príncipe Time
Africa/Lome (UTC+00:00) Togo Time
Antarctica/Troll (UTC+00:00) Troll Time
Europe/London (UTC+00:00) United Kingdom Time
Atlantic/Canary (UTC+00:00) Western European Time (Canary)
Atlantic/Faroe (UTC+00:00) Western European Time (Faroe)
Europe/Lisbon (UTC+00:00) Western European Time (Lisbon)
Atlantic/Madeira (UTC+00:00) Western European Time (Madeira)
Africa/El_Aaiun (UTC+00:00) Western Sahara Time
Africa/Algiers (UTC+01:00) Central European Time (Algiers)
Europe/Amsterdam (UTC+01:00) Central European Time (Amsterdam)
Europe/Andorra (UTC+01:00) Central European Time (Andorra)
Europe/Belgrade (UTC+01:00) Central European Time (Belgrade)
Europe/Berlin (UTC+01:00) Central European Time (Berlin)
Europe/Bratislava (UTC+01:00) Central European Time (Bratislava)
Europe/Brussels (UTC+01:00) Central European Time (Brussels)
Europe/Budapest (UTC+01:00) Central European Time (Budapest)
Europe/Busingen (UTC+01:00) Central European Time (Busingen)
Africa/Ceuta (UTC+01:00) Central European Time (Ceuta)
Europe/Copenhagen (UTC+01:00) Central European Time (Copenhagen)
Europe/Gibraltar (UTC+01:00) Central European Time (Gibraltar)
Europe/Ljubljana (UTC+01:00) Central European Time (Ljubljana)
Arctic/Longyearbyen (UTC+01:00) Central European Time (Longyearbyen)
Europe/Luxembourg (UTC+01:00) Central European Time (Luxembourg)
Europe/Madrid (UTC+01:00) Central European Time (Madrid)
Europe/Malta (UTC+01:00) Central European Time (Malta)
Europe/Monaco (UTC+01:00) Central European Time (Monaco)
Europe/Oslo (UTC+01:00) Central European Time (Oslo)
Europe/Paris (UTC+01:00) Central European Time (Paris)
Europe/Podgorica (UTC+01:00) Central European Time (Podgorica)
Europe/Prague (UTC+01:00) Central European Time (Prague)
Europe/Rome (UTC+01:00) Central European Time (Rome)
Europe/San_Marino (UTC+01:00) Central European Time (San Marino)
Europe/Sarajevo (UTC+01:00) Central European Time (Sarajevo)
Europe/Skopje (UTC+01:00) Central European Time (Skopje)
Europe/Stockholm (UTC+01:00) Central European Time (Stockholm)
Europe/Tirane (UTC+01:00) Central European Time (Tirane)
Africa/Tunis (UTC+01:00) Central European Time (Tunis)
Europe/Vaduz (UTC+01:00) Central European Time (Vaduz)
Europe/Vatican (UTC+01:00) Central European Time (Vatican)
Europe/Vienna (UTC+01:00) Central European Time (Vienna)
Europe/Warsaw (UTC+01:00) Central European Time (Warsaw)
Europe/Zagreb (UTC+01:00) Central European Time (Zagreb)
Europe/Zurich (UTC+01:00) Central European Time (Zurich)
Africa/Bangui (UTC+01:00) West Africa Standard Time (Bangui)
Africa/Brazzaville (UTC+01:00) West Africa Standard Time (Brazzaville)
Africa/Douala (UTC+01:00) West Africa Standard Time (Douala)
Africa/Kinshasa (UTC+01:00) West Africa Standard Time (Kinshasa)
Africa/Lagos (UTC+01:00) West Africa Standard Time (Lagos)
Africa/Libreville (UTC+01:00) West Africa Standard Time (Libreville)
Africa/Luanda (UTC+01:00) West Africa Standard Time (Luanda)
Africa/Malabo (UTC+01:00) West Africa Standard Time (Malabo)
Africa/Ndjamena (UTC+01:00) West Africa Standard Time (Ndjamena)
Africa/Niamey (UTC+01:00) West Africa Standard Time (Niamey)
Africa/Porto-Novo (UTC+01:00) West Africa Standard Time (Porto-Novo)
Africa/Blantyre (UTC+02:00) Central Africa Time (Blantyre)
Africa/Bujumbura (UTC+02:00) Central Africa Time (Bujumbura)
Africa/Gaborone (UTC+02:00) Central Africa Time (Gaborone)
Africa/Harare (UTC+02:00) Central Africa Time (Harare)
Africa/Juba (UTC+02:00) Central Africa Time (Juba)
Africa/Khartoum (UTC+02:00) Central Africa Time (Khartoum)
Africa/Kigali (UTC+02:00) Central Africa Time (Kigali)
Africa/Lubumbashi (UTC+02:00) Central Africa Time (Lubumbashi)
Africa/Lusaka (UTC+02:00) Central Africa Time (Lusaka)
Africa/Maputo (UTC+02:00) Central Africa Time (Maputo)
Africa/Windhoek (UTC+02:00) Central Africa Time (Windhoek)
Asia/Amman (UTC+02:00) Eastern European Time (Amman)
Europe/Athens (UTC+02:00) Eastern European Time (Athens)
Asia/Beirut (UTC+02:00) Eastern European Time (Beirut)
Europe/Bucharest (UTC+02:00) Eastern European Time (Bucharest)
Africa/Cairo (UTC+02:00) Eastern European Time (Cairo)
Europe/Chisinau (UTC+02:00) Eastern European Time (Chisinau)
Asia/Damascus (UTC+02:00) Eastern European Time (Damascus)
Asia/Gaza (UTC+02:00) Eastern European Time (Gaza)
Asia/Hebron (UTC+02:00) Eastern European Time (Hebron)
Europe/Helsinki (UTC+02:00) Eastern European Time (Helsinki)
Europe/Kaliningrad (UTC+02:00) Eastern European Time (Kaliningrad)
Europe/Kiev (UTC+02:00) Eastern European Time (Kiev)
Europe/Mariehamn (UTC+02:00) Eastern European Time (Mariehamn)
Asia/Nicosia (UTC+02:00) Eastern European Time (Nicosia)
Europe/Riga (UTC+02:00) Eastern European Time (Riga)
Europe/Sofia (UTC+02:00) Eastern European Time (Sofia)
Europe/Tallinn (UTC+02:00) Eastern European Time (Tallinn)
Africa/Tripoli (UTC+02:00) Eastern European Time (Tripoli)
Europe/Uzhgorod (UTC+02:00) Eastern European Time (Uzhhorod)
Europe/Vilnius (UTC+02:00) Eastern European Time (Vilnius)
Europe/Zaporozhye (UTC+02:00) Eastern European Time (Zaporozhye)
Asia/Famagusta (UTC+02:00) Famagusta Time
Asia/Jerusalem (UTC+02:00) Israel Time
Africa/Johannesburg (UTC+02:00) South Africa Standard Time (Johannesburg)
Africa/Maseru (UTC+02:00) South Africa Standard Time (Maseru)
Africa/Mbabane (UTC+02:00) South Africa Standard Time (Mbabane)
Asia/Aden (UTC+03:00) Arabian Standard Time (Aden)
Asia/Baghdad (UTC+03:00) Arabian Standard Time (Baghdad)
Asia/Bahrain (UTC+03:00) Arabian Standard Time (Bahrain)
Asia/Kuwait (UTC+03:00) Arabian Standard Time (Kuwait)
Asia/Qatar (UTC+03:00) Arabian Standard Time (Qatar)
Asia/Riyadh (UTC+03:00) Arabian Standard Time (Riyadh)
Europe/Minsk (UTC+03:00) Belarus Time
Africa/Addis_Ababa (UTC+03:00) East Africa Time (Addis Ababa)
Indian/Antananarivo (UTC+03:00) East Africa Time (Antananarivo)
Africa/Asmara (UTC+03:00) East Africa Time (Asmara)
Indian/Comoro (UTC+03:00) East Africa Time (Comoro)
Africa/Dar_es_Salaam (UTC+03:00) East Africa Time (Dar es Salaam)
Africa/Djibouti (UTC+03:00) East Africa Time (Djibouti)
Africa/Kampala (UTC+03:00) East Africa Time (Kampala)
Indian/Mayotte (UTC+03:00) East Africa Time (Mayotte)
Africa/Mogadishu (UTC+03:00) East Africa Time (Mogadishu)
Africa/Nairobi (UTC+03:00) East Africa Time (Nairobi)
Europe/Kirov (UTC+03:00) Kirov Time
Europe/Moscow (UTC+03:00) Moscow Time
Europe/Simferopol (UTC+03:00) Simferopol Time
Antarctica/Syowa (UTC+03:00) Syowa Time
Europe/Istanbul (UTC+03:00) Turkey Time
Europe/Volgograd (UTC+03:00) Volgograd Standard Time
Asia/Tehran (UTC+03:30) Iran Standard Time (Tehran)
Asia/Yerevan (UTC+04:00) Armenia Standard Time (Yerevan)
Europe/Astrakhan (UTC+04:00) Astrakhan Time
Asia/Baku (UTC+04:00) Azerbaijan Standard Time (Baku)
Asia/Tbilisi (UTC+04:00) Georgia Standard Time (Tbilisi)
Asia/Dubai (UTC+04:00) Gulf Standard Time (Dubai)
Asia/Muscat (UTC+04:00) Gulf Standard Time (Muscat)
Indian/Mauritius (UTC+04:00) Mauritius Standard Time
Indian/Reunion (UTC+04:00) Réunion Time
Europe/Samara (UTC+04:00) Samara Standard Time
Europe/Saratov (UTC+04:00) Saratov Time
Indian/Mahe (UTC+04:00) Seychelles Time
Europe/Ulyanovsk (UTC+04:00) Ulyanovsk Time
Asia/Kabul (UTC+04:30) Afghanistan Time
Indian/Kerguelen (UTC+05:00) French Southern & Antarctic Time (Kerguelen)
Indian/Maldives (UTC+05:00) Maldives Time
Antarctica/Mawson (UTC+05:00) Mawson Time
Asia/Karachi (UTC+05:00) Pakistan Standard Time (Karachi)
Asia/Dushanbe (UTC+05:00) Tajikistan Time
Asia/Ashgabat (UTC+05:00) Turkmenistan Standard Time (Ashgabat)
Asia/Samarkand (UTC+05:00) Uzbekistan Standard Time (Samarkand)
Asia/Tashkent (UTC+05:00) Uzbekistan Standard Time (Tashkent)
Asia/Aqtau (UTC+05:00) West Kazakhstan Time (Aqtau)
Asia/Aqtobe (UTC+05:00) West Kazakhstan Time (Aqtobe)
Asia/Atyrau (UTC+05:00) West Kazakhstan Time (Atyrau)
Asia/Oral (UTC+05:00) West Kazakhstan Time (Oral)
Asia/Qyzylorda (UTC+05:00) West Kazakhstan Time (Qyzylorda)
Asia/Yekaterinburg (UTC+05:00) Yekaterinburg Standard Time
Asia/Colombo (UTC+05:30) India Standard Time (Colombo)
Asia/Kolkata (UTC+05:30) India Standard Time (Kolkata)
Asia/Kathmandu (UTC+05:45) Nepal Time
Asia/Dhaka (UTC+06:00) Bangladesh Standard Time (Dhaka)
Asia/Thimphu (UTC+06:00) Bhutan Time
Asia/Almaty (UTC+06:00) East Kazakhstan Time (Almaty)
Asia/Qostanay (UTC+06:00) East Kazakhstan Time (Kostanay)
Indian/Chagos (UTC+06:00) Indian Ocean Time (Chagos)
Asia/Bishkek (UTC+06:00) Kyrgyzstan Time
Asia/Omsk (UTC+06:00) Omsk Standard Time
Asia/Urumqi (UTC+06:00) Urumqi Time
Antarctica/Vostok (UTC+06:00) Vostok Time
Indian/Cocos (UTC+06:30) Cocos Islands Time
Asia/Yangon (UTC+06:30) Myanmar Time (Yangon)
Asia/Barnaul (UTC+07:00) Barnaul Time
Indian/Christmas (UTC+07:00) Christmas Island Time
Antarctica/Davis (UTC+07:00) Davis Time
Asia/Hovd (UTC+07:00) Hovd Standard Time
Asia/Bangkok (UTC+07:00) Indochina Time (Bangkok)
Asia/Ho_Chi_Minh (UTC+07:00) Indochina Time (Ho Chi Minh City)
Asia/Phnom_Penh (UTC+07:00) Indochina Time (Phnom Penh)
Asia/Vientiane (UTC+07:00) Indochina Time (Vientiane)
Asia/Krasnoyarsk (UTC+07:00) Krasnoyarsk Standard Time
Asia/Novokuznetsk (UTC+07:00) Krasnoyarsk Standard Time (Novokuznetsk)
Asia/Novosibirsk (UTC+07:00) Novosibirsk Standard Time
Asia/Tomsk (UTC+07:00) Tomsk Time
Asia/Jakarta (UTC+07:00) Western Indonesia Time (Jakarta)
Asia/Pontianak (UTC+07:00) Western Indonesia Time (Pontianak)
Australia/Perth (UTC+08:00) Australian Western Standard Time (Perth)
Asia/Brunei (UTC+08:00) Brunei Darussalam Time
Asia/Makassar (UTC+08:00) Central Indonesia Time (Makassar)
Asia/Macau (UTC+08:00) China Standard Time (Macao)
Asia/Shanghai (UTC+08:00) China Standard Time (Shanghai)
Asia/Hong_Kong (UTC+08:00) Hong Kong Standard Time
Asia/Irkutsk (UTC+08:00) Irkutsk Standard Time
Asia/Kuala_Lumpur (UTC+08:00) Malaysia Time
Asia/Kuching (UTC+08:00) Malaysia Time (Kuching)
Asia/Manila (UTC+08:00) Philippine Standard Time (Manila)
Asia/Singapore (UTC+08:00) Singapore Standard Time
Asia/Taipei (UTC+08:00) Taipei Standard Time
Asia/Ulaanbaatar (UTC+08:00) Ulaanbaatar Standard Time
Asia/Choibalsan (UTC+08:00) Ulaanbaatar Standard Time (Choibalsan)
Australia/Eucla (UTC+08:45) Australian Central Western Standard Time (Eucla)
Asia/Dili (UTC+09:00) East Timor Time (Dili)
Asia/Jayapura (UTC+09:00) Eastern Indonesia Time (Jayapura)
Asia/Tokyo (UTC+09:00) Japan Standard Time (Tokyo)
Asia/Pyongyang (UTC+09:00) Korean Standard Time (Pyongyang)
Asia/Seoul (UTC+09:00) Korean Standard Time (Seoul)
Pacific/Palau (UTC+09:00) Palau Time
Asia/Yakutsk (UTC+09:00) Yakutsk Standard Time
Asia/Chita (UTC+09:00) Yakutsk Standard Time (Chita)
Asia/Khandyga (UTC+09:00) Yakutsk Standard Time (Khandyga)
Australia/Adelaide (UTC+09:30) Central Australia Time (Adelaide)
Australia/Broken_Hill (UTC+09:30) Central Australia Time (Broken Hill)
Australia/Darwin (UTC+09:30) Central Australia Time (Darwin)
Pacific/Guam (UTC+10:00) Chamorro Standard Time (Guam)
Pacific/Saipan (UTC+10:00) Chamorro Standard Time (Saipan)
Pacific/Chuuk (UTC+10:00) Chuuk Time
Antarctica/DumontDUrville (UTC+10:00) Dumont-d’Urville Time (Dumont d’Urville)
Australia/Brisbane (UTC+10:00) Eastern Australia Time (Brisbane)
Australia/Hobart (UTC+10:00) Eastern Australia Time (Hobart)
Australia/Lindeman (UTC+10:00) Eastern Australia Time (Lindeman)
Antarctica/Macquarie (UTC+10:00) Eastern Australia Time (Macquarie)
Australia/Melbourne (UTC+10:00) Eastern Australia Time (Melbourne)
Australia/Sydney (UTC+10:00) Eastern Australia Time (Sydney)
Pacific/Port_Moresby (UTC+10:00) Papua New Guinea Time (Port Moresby)
Asia/Vladivostok (UTC+10:00) Vladivostok Standard Time
Asia/Ust-Nera (UTC+10:00) Vladivostok Standard Time (Ust-Nera)
Australia/Lord_Howe (UTC+10:30) Lord Howe Time
Pacific/Bougainville (UTC+11:00) Bougainville Time
Antarctica/Casey (UTC+11:00) Casey Time
Pacific/Kosrae (UTC+11:00) Kosrae Time
Asia/Magadan (UTC+11:00) Magadan Standard Time
Pacific/Noumea (UTC+11:00) New Caledonia Standard Time (Noumea)
Pacific/Norfolk (UTC+11:00) Norfolk Island Time
Pacific/Pohnpei (UTC+11:00) Ponape Time (Pohnpei)
Asia/Sakhalin (UTC+11:00) Sakhalin Standard Time
Pacific/Guadalcanal (UTC+11:00) Solomon Islands Time
Asia/Srednekolymsk (UTC+11:00) Srednekolymsk Time
Pacific/Efate (UTC+11:00) Vanuatu Standard Time (Efate)
Asia/Anadyr (UTC+12:00) Anadyr Standard Time
Pacific/Fiji (UTC+12:00) Fiji Time
Pacific/Tarawa (UTC+12:00) Gilbert Islands Time (Tarawa)
Pacific/Majuro (UTC+12:00) Marshall Islands Time
Pacific/Kwajalein (UTC+12:00) Marshall Islands Time (Kwajalein)
Pacific/Nauru (UTC+12:00) Nauru Time
Pacific/Auckland (UTC+12:00) New Zealand Time
Antarctica/McMurdo (UTC+12:00) New Zealand Time (McMurdo)
Asia/Kamchatka (UTC+12:00) Petropavlovsk-Kamchatski Standard Time (Kamchatka)
Pacific/Funafuti (UTC+12:00) Tuvalu Time
Pacific/Wake (UTC+12:00) Wake Island Time
Pacific/Wallis (UTC+12:00) Wallis & Futuna Time
Pacific/Chatham (UTC+12:45) Chatham Time
Pacific/Enderbury (UTC+13:00) Phoenix Islands Time (Enderbury)
Pacific/Apia (UTC+13:00) Samoa Time
Pacific/Fakaofo (UTC+13:00) Tokelau Time
Pacific/Tongatapu (UTC+13:00) Tonga Standard Time (Tongatapu)
Pacific/Kiritimati (UTC+14:00) Line Islands Time (Kiritimati)

After

(click to expand)
Id Display Name
Pacific/Midway (UTC-11:00) Samoa Standard Time (Midway)
Pacific/Niue (UTC-11:00) Niue Time
Pacific/Pago_Pago (UTC-11:00) Samoa Standard Time (Pago Pago)
America/Adak (UTC-10:00) Hawaii-Aleutian Time (Adak)
Pacific/Honolulu (UTC-10:00) Hawaii-Aleutian Time (Adak) (Honolulu)
Pacific/Rarotonga (UTC-10:00) Cook Islands Standard Time (Rarotonga)
Pacific/Tahiti (UTC-10:00) Tahiti Time
Pacific/Marquesas (UTC-09:30) Marquesas Time
America/Anchorage (UTC-09:00) Alaska Time (Anchorage)
America/Juneau (UTC-09:00) Alaska Time (Juneau)
America/Metlakatla (UTC-09:00) Alaska Time (Metlakatla)
America/Nome (UTC-09:00) Alaska Time (Nome)
America/Sitka (UTC-09:00) Alaska Time (Sitka)
America/Yakutat (UTC-09:00) Alaska Time (Yakutat)
Pacific/Gambier (UTC-09:00) Gambier Time
America/Los_Angeles (UTC-08:00) Pacific Time (Los Angeles)
America/Tijuana (UTC-08:00) Pacific Time (Tijuana)
America/Vancouver (UTC-08:00) Pacific Time (Vancouver)
Pacific/Pitcairn (UTC-08:00) Pitcairn Islands Time
America/Boise (UTC-07:00) Mountain Time (Boise)
America/Cambridge_Bay (UTC-07:00) Mountain Time (Cambridge Bay)
America/Chihuahua (UTC-07:00) Mexican Pacific Time (Chihuahua)
America/Creston (UTC-07:00) Mountain Time (Creston)
America/Dawson (UTC-07:00) Yukon Time (Dawson)
America/Dawson_Creek (UTC-07:00) Mountain Time (Dawson Creek)
America/Denver (UTC-07:00) Mountain Time (Denver)
America/Edmonton (UTC-07:00) Mountain Time (Edmonton)
America/Fort_Nelson (UTC-07:00) Mountain Time (Fort Nelson)
America/Hermosillo (UTC-07:00) Mexican Pacific Time (Hermosillo)
America/Inuvik (UTC-07:00) Mountain Time (Inuvik)
America/Mazatlan (UTC-07:00) Mexican Pacific Time (Mazatlan)
America/Ojinaga (UTC-07:00) Mountain Time (Ojinaga)
America/Phoenix (UTC-07:00) Mountain Time (Phoenix)
America/Whitehorse (UTC-07:00) Yukon Time (Whitehorse)
America/Yellowknife (UTC-07:00) Mountain Time (Yellowknife)
America/Bahia_Banderas (UTC-06:00) Central Time (Bahia Banderas)
America/Belize (UTC-06:00) Central Time (Belize)
America/Chicago (UTC-06:00) Central Time (Chicago)
America/Costa_Rica (UTC-06:00) Central Time (Costa Rica)
America/El_Salvador (UTC-06:00) Central Time (El Salvador)
America/Guatemala (UTC-06:00) Central Time (Guatemala)
America/Indiana/Knox (UTC-06:00) Central Time (Knox, Indiana)
America/Indiana/Tell_City (UTC-06:00) Central Time (Tell City, Indiana)
America/Managua (UTC-06:00) Central Time (Managua)
America/Matamoros (UTC-06:00) Central Time (Matamoros)
America/Menominee (UTC-06:00) Central Time (Menominee)
America/Merida (UTC-06:00) Central Time (Merida)
America/Mexico_City (UTC-06:00) Central Time (Mexico City)
America/Monterrey (UTC-06:00) Central Time (Monterrey)
America/North_Dakota/Beulah (UTC-06:00) Central Time (Beulah, North Dakota)
America/North_Dakota/Center (UTC-06:00) Central Time (Center, North Dakota)
America/North_Dakota/New_Salem (UTC-06:00) Central Time (New Salem, North Dakota)
America/Rainy_River (UTC-06:00) Central Time (Rainy River)
America/Rankin_Inlet (UTC-06:00) Central Time (Rankin Inlet)
America/Regina (UTC-06:00) Central Time (Regina)
America/Resolute (UTC-06:00) Central Time (Resolute)
America/Swift_Current (UTC-06:00) Central Time (Swift Current)
America/Tegucigalpa (UTC-06:00) Central Time (Tegucigalpa)
America/Winnipeg (UTC-06:00) Central Time (Winnipeg)
Pacific/Easter (UTC-06:00) Easter Island Time
Pacific/Galapagos (UTC-06:00) Galapagos Time
America/Atikokan (UTC-05:00) Eastern Time (Atikokan)
America/Bogota (UTC-05:00) Colombia Standard Time (Bogota)
America/Cancun (UTC-05:00) Eastern Time (Cancun)
America/Cayman (UTC-05:00) Eastern Time (Cayman)
America/Detroit (UTC-05:00) Eastern Time (Detroit)
America/Eirunepe (UTC-05:00) Acre Standard Time (Eirunepe)
America/Grand_Turk (UTC-05:00) Eastern Time (Grand Turk)
America/Guayaquil (UTC-05:00) Ecuador Time
America/Havana (UTC-05:00) Cuba Time
America/Indiana/Indianapolis (UTC-05:00) Eastern Time (Indianapolis)
America/Indiana/Marengo (UTC-05:00) Eastern Time (Marengo, Indiana)
America/Indiana/Petersburg (UTC-05:00) Eastern Time (Petersburg, Indiana)
America/Indiana/Vevay (UTC-05:00) Eastern Time (Vevay, Indiana)
America/Indiana/Vincennes (UTC-05:00) Eastern Time (Vincennes, Indiana)
America/Indiana/Winamac (UTC-05:00) Eastern Time (Winamac, Indiana)
America/Iqaluit (UTC-05:00) Eastern Time (Iqaluit)
America/Jamaica (UTC-05:00) Eastern Time (Jamaica)
America/Kentucky/Louisville (UTC-05:00) Eastern Time (Louisville)
America/Kentucky/Monticello (UTC-05:00) Eastern Time (Monticello, Kentucky)
America/Lima (UTC-05:00) Peru Standard Time (Lima)
America/Nassau (UTC-05:00) Eastern Time (Nassau)
America/New_York (UTC-05:00) Eastern Time (New York)
America/Nipigon (UTC-05:00) Eastern Time (Nipigon)
America/Panama (UTC-05:00) Eastern Time (Panama)
America/Pangnirtung (UTC-05:00) Eastern Time (Pangnirtung)
America/Port-au-Prince (UTC-05:00) Eastern Time (Port-au-Prince)
America/Rio_Branco (UTC-05:00) Acre Standard Time (Rio Branco)
America/Thunder_Bay (UTC-05:00) Eastern Time (Thunder Bay)
America/Toronto (UTC-05:00) Eastern Time (Toronto)
America/Anguilla (UTC-04:00) Atlantic Time (Anguilla)
America/Antigua (UTC-04:00) Atlantic Time (Antigua)
America/Aruba (UTC-04:00) Atlantic Time (Aruba)
America/Asuncion (UTC-04:00) Paraguay Time
America/Barbados (UTC-04:00) Atlantic Time (Barbados)
America/Blanc-Sablon (UTC-04:00) Atlantic Time (Blanc-Sablon)
America/Boa_Vista (UTC-04:00) Amazon Standard Time (Boa Vista)
America/Campo_Grande (UTC-04:00) Amazon Standard Time (Campo Grande)
America/Caracas (UTC-04:00) Venezuela Time
America/Cuiaba (UTC-04:00) Amazon Standard Time (Cuiaba)
America/Curacao (UTC-04:00) Atlantic Time (Curaçao)
America/Dominica (UTC-04:00) Atlantic Time (Dominica)
America/Glace_Bay (UTC-04:00) Atlantic Time (Glace Bay)
America/Goose_Bay (UTC-04:00) Atlantic Time (Goose Bay)
America/Grenada (UTC-04:00) Atlantic Time (Grenada)
America/Guadeloupe (UTC-04:00) Atlantic Time (Guadeloupe)
America/Guyana (UTC-04:00) Guyana Time
America/Halifax (UTC-04:00) Atlantic Time (Halifax)
America/Kralendijk (UTC-04:00) Atlantic Time (Kralendijk)
America/La_Paz (UTC-04:00) Bolivia Time
America/Lower_Princes (UTC-04:00) Atlantic Time (Lower Prince’s Quarter)
America/Manaus (UTC-04:00) Amazon Standard Time (Manaus)
America/Marigot (UTC-04:00) Atlantic Time (Marigot)
America/Martinique (UTC-04:00) Atlantic Time (Martinique)
America/Moncton (UTC-04:00) Atlantic Time (Moncton)
America/Montserrat (UTC-04:00) Atlantic Time (Montserrat)
America/Port_of_Spain (UTC-04:00) Atlantic Time (Port of Spain)
America/Porto_Velho (UTC-04:00) Amazon Standard Time (Porto Velho)
America/Puerto_Rico (UTC-04:00) Atlantic Time (Puerto Rico)
America/Santiago (UTC-04:00) Chile Time
America/Santo_Domingo (UTC-04:00) Atlantic Time (Santo Domingo)
America/St_Barthelemy (UTC-04:00) Atlantic Time (St. Barthélemy)
America/St_Kitts (UTC-04:00) Atlantic Time (St. Kitts)
America/St_Lucia (UTC-04:00) Atlantic Time (St. Lucia)
America/St_Thomas (UTC-04:00) Atlantic Time (St. Thomas)
America/St_Vincent (UTC-04:00) Atlantic Time (St. Vincent)
America/Thule (UTC-04:00) Atlantic Time (Thule)
America/Tortola (UTC-04:00) Atlantic Time (Tortola)
Atlantic/Bermuda (UTC-04:00) Atlantic Time (Bermuda)
America/St_Johns (UTC-03:30) Newfoundland Time (St. John’s)
America/Araguaina (UTC-03:00) Brasilia Standard Time (Araguaina)
America/Argentina/Buenos_Aires (UTC-03:00) Argentina Standard Time (Buenos Aires)
America/Argentina/Catamarca (UTC-03:00) Argentina Standard Time (Catamarca)
America/Argentina/Cordoba (UTC-03:00) Argentina Standard Time (Cordoba)
America/Argentina/Jujuy (UTC-03:00) Argentina Standard Time (Jujuy)
America/Argentina/La_Rioja (UTC-03:00) Argentina Standard Time (La Rioja)
America/Argentina/Mendoza (UTC-03:00) Argentina Standard Time (Mendoza)
America/Argentina/Rio_Gallegos (UTC-03:00) Argentina Standard Time (Rio Gallegos)
America/Argentina/Salta (UTC-03:00) Argentina Standard Time (Salta)
America/Argentina/San_Juan (UTC-03:00) Argentina Standard Time (San Juan)
America/Argentina/San_Luis (UTC-03:00) Argentina Standard Time (San Luis)
America/Argentina/Tucuman (UTC-03:00) Argentina Standard Time (Tucuman)
America/Argentina/Ushuaia (UTC-03:00) Argentina Standard Time (Ushuaia)
America/Bahia (UTC-03:00) Brasilia Standard Time (Bahia)
America/Belem (UTC-03:00) Brasilia Standard Time (Belem)
America/Cayenne (UTC-03:00) French Guiana Time
America/Fortaleza (UTC-03:00) Brasilia Standard Time (Fortaleza)
America/Maceio (UTC-03:00) Brasilia Standard Time (Maceio)
America/Miquelon (UTC-03:00) St. Pierre & Miquelon Time
America/Montevideo (UTC-03:00) Uruguay Standard Time (Montevideo)
America/Nuuk (UTC-03:00) West Greenland Time (Nuuk)
America/Paramaribo (UTC-03:00) Suriname Time
America/Punta_Arenas (UTC-03:00) Punta Arenas Time
America/Recife (UTC-03:00) Brasilia Standard Time (Recife)
America/Santarem (UTC-03:00) Brasilia Standard Time (Santarem)
America/Sao_Paulo (UTC-03:00) Brasilia Standard Time (Sao Paulo)
Antarctica/Palmer (UTC-03:00) Palmer Time
Antarctica/Rothera (UTC-03:00) Rothera Time
Atlantic/Stanley (UTC-03:00) Falkland Islands Standard Time (Stanley)
America/Noronha (UTC-02:00) Fernando de Noronha Standard Time
Atlantic/South_Georgia (UTC-02:00) South Georgia Time
America/Scoresbysund (UTC-01:00) East Greenland Time (Ittoqqortoormiit)
Atlantic/Azores (UTC-01:00) Azores Time
Atlantic/Cape_Verde (UTC-01:00) Cape Verde Standard Time
Africa/Abidjan (UTC+00:00) Côte d’Ivoire Time
Africa/Accra (UTC+00:00) Ghana Time
Africa/Bamako (UTC+00:00) Mali Time
Africa/Banjul (UTC+00:00) Gambia Time
Africa/Bissau (UTC+00:00) Guinea-Bissau Time
Africa/Casablanca (UTC+00:00) Morocco Time
Africa/Conakry (UTC+00:00) Guinea Time
Africa/Dakar (UTC+00:00) Senegal Time
Africa/El_Aaiun (UTC+00:00) Western Sahara Time
Africa/Freetown (UTC+00:00) Sierra Leone Time
Africa/Lome (UTC+00:00) Togo Time
Africa/Monrovia (UTC+00:00) Liberia Time
Africa/Nouakchott (UTC+00:00) Mauritania Time
Africa/Ouagadougou (UTC+00:00) Burkina Faso Time
Africa/Sao_Tome (UTC+00:00) São Tomé & Príncipe Time
America/Danmarkshavn (UTC+00:00) Danmarkshavn Time
Antarctica/Troll (UTC+00:00) Troll Time
Atlantic/Canary (UTC+00:00) Western European Time (Canary)
Atlantic/Faroe (UTC+00:00) Western European Time (Faroe)
Atlantic/Madeira (UTC+00:00) Western European Time (Madeira)
Atlantic/Reykjavik (UTC+00:00) Iceland Time
Atlantic/St_Helena (UTC+00:00) St. Helena Time
Europe/Dublin (UTC+00:00) Ireland Time
Europe/Guernsey (UTC+00:00) Guernsey Time
Europe/Isle_of_Man (UTC+00:00) Isle of Man Time
Europe/Jersey (UTC+00:00) Jersey Time
Europe/Lisbon (UTC+00:00) Western European Time (Lisbon)
Europe/London (UTC+00:00) United Kingdom Time
UTC (UTC) Coordinated Universal Time
Africa/Algiers (UTC+01:00) Central European Time (Algiers)
Africa/Bangui (UTC+01:00) West Africa Standard Time (Bangui)
Africa/Brazzaville (UTC+01:00) West Africa Standard Time (Brazzaville)
Africa/Ceuta (UTC+01:00) Central European Time (Ceuta)
Africa/Douala (UTC+01:00) West Africa Standard Time (Douala)
Africa/Kinshasa (UTC+01:00) West Africa Standard Time (Kinshasa)
Africa/Lagos (UTC+01:00) West Africa Standard Time (Lagos)
Africa/Libreville (UTC+01:00) West Africa Standard Time (Libreville)
Africa/Luanda (UTC+01:00) West Africa Standard Time (Luanda)
Africa/Malabo (UTC+01:00) West Africa Standard Time (Malabo)
Africa/Ndjamena (UTC+01:00) West Africa Standard Time (Ndjamena)
Africa/Niamey (UTC+01:00) West Africa Standard Time (Niamey)
Africa/Porto-Novo (UTC+01:00) West Africa Standard Time (Porto-Novo)
Africa/Tunis (UTC+01:00) Central European Time (Tunis)
Arctic/Longyearbyen (UTC+01:00) Central European Time (Longyearbyen)
Europe/Amsterdam (UTC+01:00) Central European Time (Amsterdam)
Europe/Andorra (UTC+01:00) Central European Time (Andorra)
Europe/Belgrade (UTC+01:00) Central European Time (Belgrade)
Europe/Berlin (UTC+01:00) Central European Time (Berlin)
Europe/Bratislava (UTC+01:00) Central European Time (Bratislava)
Europe/Brussels (UTC+01:00) Central European Time (Brussels)
Europe/Budapest (UTC+01:00) Central European Time (Budapest)
Europe/Busingen (UTC+01:00) Central European Time (Busingen)
Europe/Copenhagen (UTC+01:00) Central European Time (Copenhagen)
Europe/Gibraltar (UTC+01:00) Central European Time (Gibraltar)
Europe/Ljubljana (UTC+01:00) Central European Time (Ljubljana)
Europe/Luxembourg (UTC+01:00) Central European Time (Luxembourg)
Europe/Madrid (UTC+01:00) Central European Time (Madrid)
Europe/Malta (UTC+01:00) Central European Time (Malta)
Europe/Monaco (UTC+01:00) Central European Time (Monaco)
Europe/Oslo (UTC+01:00) Central European Time (Oslo)
Europe/Paris (UTC+01:00) Central European Time (Paris)
Europe/Podgorica (UTC+01:00) Central European Time (Podgorica)
Europe/Prague (UTC+01:00) Central European Time (Prague)
Europe/Rome (UTC+01:00) Central European Time (Rome)
Europe/San_Marino (UTC+01:00) Central European Time (San Marino)
Europe/Sarajevo (UTC+01:00) Central European Time (Sarajevo)
Europe/Skopje (UTC+01:00) Central European Time (Skopje)
Europe/Stockholm (UTC+01:00) Central European Time (Stockholm)
Europe/Tirane (UTC+01:00) Central European Time (Tirane)
Europe/Vaduz (UTC+01:00) Central European Time (Vaduz)
Europe/Vatican (UTC+01:00) Central European Time (Vatican)
Europe/Vienna (UTC+01:00) Central European Time (Vienna)
Europe/Warsaw (UTC+01:00) Central European Time (Warsaw)
Europe/Zagreb (UTC+01:00) Central European Time (Zagreb)
Europe/Zurich (UTC+01:00) Central European Time (Zurich)
Africa/Blantyre (UTC+02:00) Central Africa Time (Blantyre)
Africa/Bujumbura (UTC+02:00) Central Africa Time (Bujumbura)
Africa/Cairo (UTC+02:00) Eastern European Time (Cairo)
Africa/Gaborone (UTC+02:00) Central Africa Time (Gaborone)
Africa/Harare (UTC+02:00) Central Africa Time (Harare)
Africa/Johannesburg (UTC+02:00) South Africa Standard Time (Johannesburg)
Africa/Juba (UTC+02:00) Central Africa Time (Juba)
Africa/Khartoum (UTC+02:00) Central Africa Time (Khartoum)
Africa/Kigali (UTC+02:00) Central Africa Time (Kigali)
Africa/Lubumbashi (UTC+02:00) Central Africa Time (Lubumbashi)
Africa/Lusaka (UTC+02:00) Central Africa Time (Lusaka)
Africa/Maputo (UTC+02:00) Central Africa Time (Maputo)
Africa/Maseru (UTC+02:00) South Africa Standard Time (Maseru)
Africa/Mbabane (UTC+02:00) South Africa Standard Time (Mbabane)
Africa/Tripoli (UTC+02:00) Eastern European Time (Tripoli)
Africa/Windhoek (UTC+02:00) Central Africa Time (Windhoek)
Asia/Amman (UTC+02:00) Eastern European Time (Amman)
Asia/Beirut (UTC+02:00) Eastern European Time (Beirut)
Asia/Damascus (UTC+02:00) Eastern European Time (Damascus)
Asia/Famagusta (UTC+02:00) Famagusta Time
Asia/Gaza (UTC+02:00) Eastern European Time (Gaza)
Asia/Hebron (UTC+02:00) Eastern European Time (Hebron)
Asia/Jerusalem (UTC+02:00) Israel Time
Asia/Nicosia (UTC+02:00) Eastern European Time (Nicosia)
Europe/Athens (UTC+02:00) Eastern European Time (Athens)
Europe/Bucharest (UTC+02:00) Eastern European Time (Bucharest)
Europe/Chisinau (UTC+02:00) Eastern European Time (Chisinau)
Europe/Helsinki (UTC+02:00) Eastern European Time (Helsinki)
Europe/Kaliningrad (UTC+02:00) Eastern European Time (Kaliningrad)
Europe/Kiev (UTC+02:00) Eastern European Time (Kiev)
Europe/Mariehamn (UTC+02:00) Eastern European Time (Mariehamn)
Europe/Riga (UTC+02:00) Eastern European Time (Riga)
Europe/Sofia (UTC+02:00) Eastern European Time (Sofia)
Europe/Tallinn (UTC+02:00) Eastern European Time (Tallinn)
Europe/Uzhgorod (UTC+02:00) Eastern European Time (Uzhhorod)
Europe/Vilnius (UTC+02:00) Eastern European Time (Vilnius)
Europe/Zaporozhye (UTC+02:00) Eastern European Time (Zaporozhye)
Africa/Addis_Ababa (UTC+03:00) East Africa Time (Addis Ababa)
Africa/Asmara (UTC+03:00) East Africa Time (Asmara)
Africa/Dar_es_Salaam (UTC+03:00) East Africa Time (Dar es Salaam)
Africa/Djibouti (UTC+03:00) East Africa Time (Djibouti)
Africa/Kampala (UTC+03:00) East Africa Time (Kampala)
Africa/Mogadishu (UTC+03:00) East Africa Time (Mogadishu)
Africa/Nairobi (UTC+03:00) East Africa Time (Nairobi)
Antarctica/Syowa (UTC+03:00) Syowa Time
Asia/Aden (UTC+03:00) Arabian Standard Time (Aden)
Asia/Baghdad (UTC+03:00) Arabian Standard Time (Baghdad)
Asia/Bahrain (UTC+03:00) Arabian Standard Time (Bahrain)
Asia/Kuwait (UTC+03:00) Arabian Standard Time (Kuwait)
Asia/Qatar (UTC+03:00) Arabian Standard Time (Qatar)
Asia/Riyadh (UTC+03:00) Arabian Standard Time (Riyadh)
Europe/Istanbul (UTC+03:00) Turkey Time
Europe/Kirov (UTC+03:00) Kirov Time
Europe/Minsk (UTC+03:00) Belarus Time
Europe/Moscow (UTC+03:00) Moscow Time
Europe/Simferopol (UTC+03:00) Simferopol Time
Europe/Volgograd (UTC+03:00) Volgograd Standard Time
Indian/Antananarivo (UTC+03:00) East Africa Time (Antananarivo)
Indian/Comoro (UTC+03:00) East Africa Time (Comoro)
Indian/Mayotte (UTC+03:00) East Africa Time (Mayotte)
Asia/Tehran (UTC+03:30) Iran Standard Time (Tehran)
Asia/Baku (UTC+04:00) Azerbaijan Standard Time (Baku)
Asia/Dubai (UTC+04:00) Gulf Standard Time (Dubai)
Asia/Muscat (UTC+04:00) Gulf Standard Time (Muscat)
Asia/Tbilisi (UTC+04:00) Georgia Standard Time (Tbilisi)
Asia/Yerevan (UTC+04:00) Armenia Standard Time (Yerevan)
Europe/Astrakhan (UTC+04:00) Astrakhan Time
Europe/Samara (UTC+04:00) Samara Standard Time
Europe/Saratov (UTC+04:00) Saratov Time
Europe/Ulyanovsk (UTC+04:00) Ulyanovsk Time
Indian/Mahe (UTC+04:00) Seychelles Time
Indian/Mauritius (UTC+04:00) Mauritius Standard Time
Indian/Reunion (UTC+04:00) Réunion Time
Asia/Kabul (UTC+04:30) Afghanistan Time
Antarctica/Mawson (UTC+05:00) Mawson Time
Asia/Aqtau (UTC+05:00) West Kazakhstan Time (Aqtau)
Asia/Aqtobe (UTC+05:00) West Kazakhstan Time (Aqtobe)
Asia/Ashgabat (UTC+05:00) Turkmenistan Standard Time (Ashgabat)
Asia/Atyrau (UTC+05:00) West Kazakhstan Time (Atyrau)
Asia/Dushanbe (UTC+05:00) Tajikistan Time
Asia/Karachi (UTC+05:00) Pakistan Standard Time (Karachi)
Asia/Oral (UTC+05:00) West Kazakhstan Time (Oral)
Asia/Qyzylorda (UTC+05:00) West Kazakhstan Time (Qyzylorda)
Asia/Samarkand (UTC+05:00) Uzbekistan Standard Time (Samarkand)
Asia/Tashkent (UTC+05:00) Uzbekistan Standard Time (Tashkent)
Asia/Yekaterinburg (UTC+05:00) Yekaterinburg Standard Time
Indian/Kerguelen (UTC+05:00) French Southern & Antarctic Time (Kerguelen)
Indian/Maldives (UTC+05:00) Maldives Time
Asia/Colombo (UTC+05:30) India Standard Time (Colombo)
Asia/Kolkata (UTC+05:30) India Standard Time (Kolkata)
Asia/Kathmandu (UTC+05:45) Nepal Time
Antarctica/Vostok (UTC+06:00) Vostok Time
Asia/Almaty (UTC+06:00) East Kazakhstan Time (Almaty)
Asia/Bishkek (UTC+06:00) Kyrgyzstan Time
Asia/Dhaka (UTC+06:00) Bangladesh Standard Time (Dhaka)
Asia/Omsk (UTC+06:00) Omsk Standard Time
Asia/Qostanay (UTC+06:00) East Kazakhstan Time (Kostanay)
Asia/Thimphu (UTC+06:00) Bhutan Time
Asia/Urumqi (UTC+06:00) Urumqi Time
Indian/Chagos (UTC+06:00) Indian Ocean Time (Chagos)
Asia/Yangon (UTC+06:30) Myanmar Time (Yangon)
Indian/Cocos (UTC+06:30) Cocos Islands Time
Antarctica/Davis (UTC+07:00) Davis Time
Asia/Bangkok (UTC+07:00) Indochina Time (Bangkok)
Asia/Barnaul (UTC+07:00) Barnaul Time
Asia/Ho_Chi_Minh (UTC+07:00) Indochina Time (Ho Chi Minh City)
Asia/Hovd (UTC+07:00) Hovd Standard Time
Asia/Jakarta (UTC+07:00) Western Indonesia Time (Jakarta)
Asia/Krasnoyarsk (UTC+07:00) Krasnoyarsk Standard Time
Asia/Novokuznetsk (UTC+07:00) Krasnoyarsk Standard Time (Novokuznetsk)
Asia/Novosibirsk (UTC+07:00) Novosibirsk Standard Time
Asia/Phnom_Penh (UTC+07:00) Indochina Time (Phnom Penh)
Asia/Pontianak (UTC+07:00) Western Indonesia Time (Pontianak)
Asia/Tomsk (UTC+07:00) Tomsk Time
Asia/Vientiane (UTC+07:00) Indochina Time (Vientiane)
Indian/Christmas (UTC+07:00) Christmas Island Time
Asia/Brunei (UTC+08:00) Brunei Darussalam Time
Asia/Choibalsan (UTC+08:00) Ulaanbaatar Standard Time (Choibalsan)
Asia/Hong_Kong (UTC+08:00) Hong Kong Standard Time
Asia/Irkutsk (UTC+08:00) Irkutsk Standard Time
Asia/Kuala_Lumpur (UTC+08:00) Malaysia Time
Asia/Kuching (UTC+08:00) Malaysia Time (Kuching)
Asia/Macau (UTC+08:00) China Standard Time (Macao)
Asia/Makassar (UTC+08:00) Central Indonesia Time (Makassar)
Asia/Manila (UTC+08:00) Philippine Standard Time (Manila)
Asia/Shanghai (UTC+08:00) China Standard Time (Shanghai)
Asia/Singapore (UTC+08:00) Singapore Standard Time
Asia/Taipei (UTC+08:00) Taipei Standard Time
Asia/Ulaanbaatar (UTC+08:00) Ulaanbaatar Standard Time
Australia/Perth (UTC+08:00) Australian Western Standard Time (Perth)
Australia/Eucla (UTC+08:45) Australian Central Western Standard Time (Eucla)
Asia/Chita (UTC+09:00) Yakutsk Standard Time (Chita)
Asia/Dili (UTC+09:00) East Timor Time (Dili)
Asia/Jayapura (UTC+09:00) Eastern Indonesia Time (Jayapura)
Asia/Khandyga (UTC+09:00) Yakutsk Standard Time (Khandyga)
Asia/Pyongyang (UTC+09:00) Korean Standard Time (Pyongyang)
Asia/Seoul (UTC+09:00) Korean Standard Time (Seoul)
Asia/Tokyo (UTC+09:00) Japan Standard Time (Tokyo)
Asia/Yakutsk (UTC+09:00) Yakutsk Standard Time
Pacific/Palau (UTC+09:00) Palau Time
Australia/Adelaide (UTC+09:30) Central Australia Time (Adelaide)
Australia/Broken_Hill (UTC+09:30) Central Australia Time (Broken Hill)
Australia/Darwin (UTC+09:30) Central Australia Time (Darwin)
Antarctica/DumontDUrville (UTC+10:00) Dumont-d’Urville Time (Dumont d’Urville)
Antarctica/Macquarie (UTC+10:00) Eastern Australia Time (Macquarie)
Asia/Ust-Nera (UTC+10:00) Vladivostok Standard Time (Ust-Nera)
Asia/Vladivostok (UTC+10:00) Vladivostok Standard Time
Australia/Brisbane (UTC+10:00) Eastern Australia Time (Brisbane)
Australia/Hobart (UTC+10:00) Eastern Australia Time (Hobart)
Australia/Lindeman (UTC+10:00) Eastern Australia Time (Lindeman)
Australia/Melbourne (UTC+10:00) Eastern Australia Time (Melbourne)
Australia/Sydney (UTC+10:00) Eastern Australia Time (Sydney)
Pacific/Chuuk (UTC+10:00) Chuuk Time
Pacific/Guam (UTC+10:00) Chamorro Standard Time (Guam)
Pacific/Port_Moresby (UTC+10:00) Papua New Guinea Time (Port Moresby)
Pacific/Saipan (UTC+10:00) Chamorro Standard Time (Saipan)
Australia/Lord_Howe (UTC+10:30) Lord Howe Time
Antarctica/Casey (UTC+11:00) Casey Time
Asia/Magadan (UTC+11:00) Magadan Standard Time
Asia/Sakhalin (UTC+11:00) Sakhalin Standard Time
Asia/Srednekolymsk (UTC+11:00) Srednekolymsk Time
Pacific/Bougainville (UTC+11:00) Bougainville Time
Pacific/Efate (UTC+11:00) Vanuatu Standard Time (Efate)
Pacific/Guadalcanal (UTC+11:00) Solomon Islands Time
Pacific/Kosrae (UTC+11:00) Kosrae Time
Pacific/Norfolk (UTC+11:00) Norfolk Island Time
Pacific/Noumea (UTC+11:00) New Caledonia Standard Time (Noumea)
Pacific/Pohnpei (UTC+11:00) Ponape Time (Pohnpei)
Antarctica/McMurdo (UTC+12:00) New Zealand Time (McMurdo)
Asia/Anadyr (UTC+12:00) Anadyr Standard Time
Asia/Kamchatka (UTC+12:00) Petropavlovsk-Kamchatski Standard Time (Kamchatka)
Pacific/Auckland (UTC+12:00) New Zealand Time
Pacific/Fiji (UTC+12:00) Fiji Time
Pacific/Funafuti (UTC+12:00) Tuvalu Time
Pacific/Kwajalein (UTC+12:00) Marshall Islands Time (Kwajalein)
Pacific/Majuro (UTC+12:00) Marshall Islands Time
Pacific/Nauru (UTC+12:00) Nauru Time
Pacific/Tarawa (UTC+12:00) Gilbert Islands Time (Tarawa)
Pacific/Wake (UTC+12:00) Wake Island Time
Pacific/Wallis (UTC+12:00) Wallis & Futuna Time
Pacific/Chatham (UTC+12:45) Chatham Time
Pacific/Apia (UTC+13:00) Samoa Time
Pacific/Enderbury (UTC+13:00) Phoenix Islands Time (Enderbury)
Pacific/Fakaofo (UTC+13:00) Tokelau Time
Pacific/Tongatapu (UTC+13:00) Tonga Standard Time (Tongatapu)
Pacific/Kiritimati (UTC+14:00) Line Islands Time (Kiritimati)
Author: mdh1418
Assignees: mdh1418
Labels:

area-System.DateTime

Milestone: -

Copy link
Contributor

@grendello grendello left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

After the build errors are fixed, I think it looks good

@@ -875,7 +902,7 @@ public static ReadOnlyCollection<TimeZoneInfo> GetSystemTimeZones()
{
// sort by BaseUtcOffset first and by DisplayName second - this is similar to the Windows Date/Time control panel
int comparison = x.BaseUtcOffset.CompareTo(y.BaseUtcOffset);
return comparison == 0 ? string.CompareOrdinal(x.DisplayName, y.DisplayName) : comparison;
return comparison == 0 ? string.CompareOrdinal(x.Id, y.Id) : comparison;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

return comparison == 0 ? string.CompareOrdinal(x.Id, y.Id) : comparison;

This is wrong. Usually the list is populated to the UI in most common cases and should be sorted according the display name and not the Id.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorting by DisplayName will hurt performance considerably because this line may be the first call to lazily load the DisplayNames. When ordering by Id, this sort operation takes 1ms, when ordering by DisplayName, this sort operation takes >400ms (on my machine, for slow android phones it will take even longer).

I am wondering what percentage of users that use GetSystemTimeZones need the timezones to be sorted on DisplayName, if a majority of users don't need to use DisplayName, I think it would be unfair to make all users who grab GetSystemTimeZones for other properties to need to take this significant perf hit. Loading StandardName and DaylightName together take 1/9th of the time that DisplayName takes overall (based on timings within TryPopulateTimeZoneDisplayNamesFromGlobalizationData). Would it make sense to have a separate function like GetSystemTimeZones + GetSystemTimeZonesSortedByDisplayName?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a breaking change. The behavior is documented.

https://learn.microsoft.com/en-us/dotnet/api/system.timezoneinfo.getsystemtimezones?view=net-7.0#remarks

The collection returned by this method is sorted by UTC offset and, for time zones that have the same UTC offset, by the display name using the current culture.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would adding another API for users that want to grab all system time zones (regardless of ordering) but care more about performance make sense?

Copy link
Member

@tarekgh tarekgh Jul 5, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apps usually call GetSystemTimeZones once and not in the startup code paths. I never saw any perf concern with that. Why is the perf concern here? do you have a real app/service suffer from the perf because of that? it should be one call cost and then forget it. by the way, the majority of usage of this API is the apps displaying the list of time zones in the UI allow users to select one. It is reasonable to pay the cost of getting the display name.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And I don't think we need to expose a new API except if we have evidence there is a perf issue blocking apps/services.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There was this original issue that this PR aims to remedy dotnet/android#8050.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I posted a question to the guy who opened the issue there. It is not clear to me why he needs to enumerate all time zones to do time zone conversions.

// Keep window's implementation to populate via constructor
return null;
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

would these ever be called on Windows? if not, then at least assert or throw exception here to catch any future wrong use of it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like there could be cases where _displayName is still null, like when using the public APIs CreateCustomTimeZone. So if for some reason someone used TimeZoneInfo myTzi = CreateCustomTimeZone(<id>, <offset>, null, null, null, <adjustmentRules>) and later invoked myTzi.DisplayName, this would be hit.

I think in this case, we should honor that the internal fields have not been set and still return null?
But thats a good point.... I wouldn't want TimeZoneInfo objects created by CreateCustomTimeZone to have their fields unexpectedly populated (and incur the performance hit) if they intended for them to have a null value.

Would the best way to check that be by having some sort of boolean to track whether or not it had been set as null on purpose?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now that CreateCustomTimeZone sets the names to string.Empty if they were null, these shouldn't be hit.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added Debug.Assert(false); in the window's implementation of these methods.

I modified the primary constructor in TimeZoneInfo.cs to have ?? string.Empty for the internal fields (and removed the modifications from CreateCustomTimeZone as they will eventually flow to this constructor.

private TimeZoneInfo(
                string id,
                TimeSpan baseUtcOffset,
                string? displayName,
                string? standardDisplayName,
                string? daylightDisplayName,
                AdjustmentRule[]? adjustmentRules,
                bool disableDaylightSavingTime,
                bool hasIanaId = false)

In doing so, I believe for windows the only other TimeZoneInfo constructor that is of interest is

private TimeZoneInfo(in TIME_ZONE_INFORMATION zone, bool dstDisabled)
, which sets the fields to non null values, so we should not hit these Populate* methods on Windows (unless I'm missing something else)

Moreover, this doesn't get used anywhere does it?

private TimeZoneInfo(SerializationInfo info, StreamingContext context)
{
ArgumentNullException.ThrowIfNull(info);
_id = (string)info.GetValue("Id", typeof(string))!; // Do not rename (binary serialization)
_displayName = (string?)info.GetValue("DisplayName", typeof(string)); // Do not rename (binary serialization)
_standardDisplayName = (string?)info.GetValue("StandardName", typeof(string)); // Do not rename (binary serialization)
_daylightDisplayName = (string?)info.GetValue("DaylightName", typeof(string)); // Do not rename (binary serialization)
_baseUtcOffset = (TimeSpan)info.GetValue("BaseUtcOffset", typeof(TimeSpan))!; // Do not rename (binary serialization)
_adjustmentRules = (AdjustmentRule[]?)info.GetValue("AdjustmentRules", typeof(AdjustmentRule[])); // Do not rename (binary serialization)
_supportsDaylightSavingTime = (bool)info.GetValue("SupportsDaylightSavingTime", typeof(bool))!; // Do not rename (binary serialization)
}

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this doesn't get used anywhere does it?

I recall it can be used by some serialization engines like Data Contract serialization. Please keep it for compat.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah even though it is a private constructor and isn't referenced in the TimeZoneInfo.*.cs?

Copy link
Member

@tarekgh tarekgh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Left few comments.

@ghost ghost added the needs-author-action An issue or pull request that requires more info or actions from the author. label Jul 4, 2023
@tarekgh tarekgh added this to the 8.0.0 milestone Jul 4, 2023
@tarekgh
Copy link
Member

tarekgh commented Jul 4, 2023

CC @mattjohnsonpint

@ghost ghost removed the needs-author-action An issue or pull request that requires more info or actions from the author. label Jul 5, 2023
@mdh1418 mdh1418 force-pushed the android_perf_timezoneinfo branch from e522b25 to e933ea0 Compare July 5, 2023 14:13
@mdh1418 mdh1418 force-pushed the android_perf_timezoneinfo branch from d46701a to b453345 Compare July 5, 2023 19:15
Comment on lines +88 to +90
timeZone.DisplayName,
timeZone.StandardName,
timeZone.DaylightName,
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Needed to invoke the lazy initialization because _displayName would not be populated otherwise.

@mdh1418 mdh1418 force-pushed the android_perf_timezoneinfo branch from 7bad4cd to e60c1a4 Compare July 5, 2023 23:11
Copy link
Member

@tarekgh tarekgh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM. ensure clean CI and addressing #88368 (review).
Thanks @mdh1418.

@mdh1418 mdh1418 force-pushed the android_perf_timezoneinfo branch from 5fd4e14 to a47ea8c Compare July 6, 2023 06:22
@mdh1418
Copy link
Member Author

mdh1418 commented Jul 10, 2023

Failures were known #88499

@mdh1418 mdh1418 merged commit a772aa3 into dotnet:main Jul 10, 2023
159 of 166 checks passed
@mdh1418 mdh1418 deleted the android_perf_timezoneinfo branch July 10, 2023 14:07
@ghost ghost locked as resolved and limited conversation to collaborators Aug 13, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Calling System.TimeZoneInfo.GetSystemTimeZones() is unacceptable slow calling it the first time.
4 participants