How to shorten the timezone name list got from moment.js?

I am using moment.js ( the method I used is moment.tz.names()) to retrieve the timezone name list which enumerates over 500 cities across the world. The long list makes it not very efficient for the users to pick up the desired timezone. The question is whether there is a way to cut down on the size of the list, meaning group the cities in the same timezone offset together.


Solution 1:

Here are the Microsoft Time Zone Index Values, mentioned in another answer here by @stanleyxu2005.

{000, "Dateline Standard Time", "(GMT-12:00) International Date Line West"},
{001, "Samoa Standard Time", "(GMT-11:00) Midway Island, Samoa"},
{002, "Hawaiian Standard Time", "(GMT-10:00) Hawaii"},
{003, "Alaskan Standard Time", "(GMT-09:00) Alaska"},
{004, "Pacific Standard Time", "(GMT-08:00) Pacific Time (US and Canada); Tijuana"},
{010, "Mountain Standard Time", "(GMT-07:00) Mountain Time (US and Canada)"},
{013, "Mexico Standard Time 2", "(GMT-07:00) Chihuahua, La Paz, Mazatlan"},
{015, "U.S. Mountain Standard Time", "(GMT-07:00) Arizona"},
{020, "Central Standard Time", "(GMT-06:00) Central Time (US and Canada"},
{025, "Canada Central Standard Time", "(GMT-06:00) Saskatchewan"},
{030, "Mexico Standard Time", "(GMT-06:00) Guadalajara, Mexico City, Monterrey"},
{033, "Central America Standard Time", "(GMT-06:00) Central America"},
{035, "Eastern Standard Time", "(GMT-05:00) Eastern Time (US and Canada)"},
{040, "U.S. Eastern Standard Time", "(GMT-05:00) Indiana (East)"},
{045, "S.A. Pacific Standard Time", "(GMT-05:00) Bogota, Lima, Quito"},
{050, "Atlantic Standard Time", "(GMT-04:00) Atlantic Time (Canada)"},
{055, "S.A. Western Standard Time", "(GMT-04:00) Caracas, La Paz"},
{056, "Pacific S.A. Standard Time", "(GMT-04:00) Santiago"},
{060, "Newfoundland and Labrador Standard Time", "(GMT-03:30) Newfoundland and Labrador"},
{065, "E. South America Standard Time", "(GMT-03:00) Brasilia"},
{070, "S.A. Eastern Standard Time", "(GMT-03:00) Buenos Aires, Georgetown"},
{073, "Greenland Standard Time", "(GMT-03:00) Greenland"},
{075, "Mid-Atlantic Standard Time", "(GMT-02:00) Mid-Atlantic"},
{080, "Azores Standard Time", "(GMT-01:00) Azores"},
{083, "Cape Verde Standard Time", "(GMT-01:00) Cape Verde Islands"},
{085, "GMT Standard Time", "(GMT) Greenwich Mean Time: Dublin, Edinburgh, Lisbon, London"},
{090, "Greenwich Standard Time", "(GMT) Casablanca, Monrovia"},
{095, "Central Europe Standard Time", "(GMT+01:00) Belgrade, Bratislava, Budapest, Ljubljana, Prague"},
{100, "Central European Standard Time", "(GMT+01:00) Sarajevo, Skopje, Warsaw, Zagreb"},
{105, "Romance Standard Time", "(GMT+01:00) Brussels, Copenhagen, Madrid, Paris"},
{110, "W. Europe Standard Time", "(GMT+01:00) Amsterdam, Berlin, Bern, Rome, Stockholm, Vienna"},
{113, "W. Central Africa Standard Time", "(GMT+01:00) West Central Africa"},
{115, "E. Europe Standard Time", "(GMT+02:00) Bucharest"},
{120, "Egypt Standard Time", "(GMT+02:00) Cairo"},
{125, "FLE Standard Time", "(GMT+02:00) Helsinki, Kiev, Riga, Sofia, Tallinn, Vilnius"},
{130, "GTB Standard Time", "(GMT+02:00) Athens, Istanbul, Minsk"},
{135, "Israel Standard Time", "(GMT+02:00) Jerusalem"},
{140, "South Africa Standard Time", "(GMT+02:00) Harare, Pretoria"},
{145, "Russian Standard Time", "(GMT+03:00) Moscow, St. Petersburg, Volgograd"},
{150, "Arab Standard Time", "(GMT+03:00) Kuwait, Riyadh"},
{155, "E. Africa Standard Time", "(GMT+03:00) Nairobi"},
{158, "Arabic Standard Time", "(GMT+03:00) Baghdad"},
{160, "Iran Standard Time", "(GMT+03:30) Tehran"},
{165, "Arabian Standard Time", "(GMT+04:00) Abu Dhabi, Muscat"},
{170, "Caucasus Standard Time", "(GMT+04:00) Baku, Tbilisi, Yerevan"},
{175, "Transitional Islamic State of Afghanistan Standard Time", "(GMT+04:30) Kabul"},
{180, "Ekaterinburg Standard Time", "(GMT+05:00) Ekaterinburg"},
{185, "West Asia Standard Time", "(GMT+05:00) Islamabad, Karachi, Tashkent"},
{190, "India Standard Time", "(GMT+05:30) Chennai, Kolkata, Mumbai, New Delhi"},
{193, "Nepal Standard Time", "(GMT+05:45) Kathmandu"},
{195, "Central Asia Standard Time", "(GMT+06:00) Astana, Dhaka"},
{200, "Sri Lanka Standard Time", "(GMT+06:00) Sri Jayawardenepura"},
{201, "N. Central Asia Standard Time", "(GMT+06:00) Almaty, Novosibirsk"},
{203, "Myanmar Standard Time", "(GMT+06:30) Yangon Rangoon"},
{205, "S.E. Asia Standard Time", "(GMT+07:00) Bangkok, Hanoi, Jakarta"},
{207, "North Asia Standard Time", "(GMT+07:00) Krasnoyarsk"},
{210, "China Standard Time", "(GMT+08:00) Beijing, Chongqing, Hong Kong SAR, Urumqi"},
{215, "Singapore Standard Time", "(GMT+08:00) Kuala Lumpur, Singapore"},
{220, "Taipei Standard Time", "(GMT+08:00) Taipei"},
{225, "W. Australia Standard Time", "(GMT+08:00) Perth"},
{227, "North Asia East Standard Time", "(GMT+08:00) Irkutsk, Ulaanbaatar"},
{230, "Korea Standard Time", "(GMT+09:00) Seoul"},
{235, "Tokyo Standard Time", "(GMT+09:00) Osaka, Sapporo, Tokyo"},
{240, "Yakutsk Standard Time", "(GMT+09:00) Yakutsk"},
{245, "A.U.S. Central Standard Time", "(GMT+09:30) Darwin"},
{250, "Cen. Australia Standard Time", "(GMT+09:30) Adelaide"},
{255, "A.U.S. Eastern Standard Time", "(GMT+10:00) Canberra, Melbourne, Sydney"},
{260, "E. Australia Standard Time", "(GMT+10:00) Brisbane"},
{265, "Tasmania Standard Time", "(GMT+10:00) Hobart"},
{270, "Vladivostok Standard Time", "(GMT+10:00) Vladivostok"},
{275, "West Pacific Standard Time", "(GMT+10:00) Guam, Port Moresby"},
{280, "Central Pacific Standard Time", "(GMT+11:00) Magadan, Solomon Islands, New Caledonia"},
{285, "Fiji Islands Standard Time", "(GMT+12:00) Fiji Islands, Kamchatka, Marshall Islands"},
{290, "New Zealand Standard Time", "(GMT+12:00) Auckland, Wellington"},
{300, "Tonga Standard Time", "(GMT+13:00) Nuku'alofa"}

Solution 2:

This is something on the backlog for moment-timezone, in issue #227.

Below is the temporary workaround I provided there, which will shorten the list to 365 zone identifiers.

var names = Object.keys(moment.tz._zones)
    .map(function(k) { return moment.tz._zones[k].split('|')[0]; })
    .filter(function(z) { return z.indexOf('/') >= 0; })
    .sort();

This removes links and abbreviated zones from the list. We recognize this is still not ideal, and will improve upon this in a future release.

Solution 3:

I think this is not a technical question but a design question. Showing 500+ cities in a dropdown list is not good UI design.

Here are some alternative ways:

  1. Show timezone abbreviations, e.g. ['CST', 'EST', ...] or ['UTC', 'UTC+1', ...].
  2. Maintain a reduced timezone list. For every timezone, show 2-3 most famous cities. Please refer the timezone settings of Windows.

I hope this can be helpful to you.

Solution 4:

In case someone else would like to filter out deprecated timezones:

const deprecatedTimeZones = ["UCT", "PST8PDT", "GB", "MST7MDT", "EST5EDT", "W-SU", "CST6CDT", "HST", "MST", "Universal", "EET", "WET", "EST", "CET", "MET", "GMT", "Etc"];
const deprecatedTimeZonesRegex = `^${deprecatedTimeZones.join("|^")}`;

const allowedTimeZones = moment.tz.names()
    .filter(timezone => timezone.startsWith("A") || !new RegExp(deprecatedTimeZonesRegex).test(timezone))
    .sort((timezoneA, timezoneB) => timezoneA.localeCompare(timezoneB))
    .map(timezone => ({
        timezone,
    }));

Using react-select (or something similar) in frontend for selection will make this fine.