Moment-timezone: Only "formal", non-backwards compatible names of timezones ?

Created on 2 Jun 2015  ·  17Comments  ·  Source: moment/moment-timezone

How do I get a list of all the "offical" timezones and not old/backwards compatible names ?
Such weird/old names are GB, EST5EDT, etc.. ?

enhancement

Most helpful comment

The above is incorrect, plenty of valid ones do not start with Continent/ or Ocean/ - UTC and GMT are a couple of examples of this.

I don't think this issue can be solved well with a regex, we need to just be able to pass an option to just get the current ones.

All 17 comments

There's nothing built in, but you could filter the list with a regex, like so:

moment.tz.names().filter(function(s){ return /\//.test(s); })

That just filters to those that contain a / character. You might want additional filtering, such as allowing "UTC" and omitting the other "Etc/*" zones.

It would be nice if there was some distinction between canonical and noncanonical zones, or if there was a simple way to return the list of zones that are intended for time zone selection. That would use zone.tab or zone1970.tab data, similar to how tzselect works.

As a temporary workaround, the following will at least provide a list of canonical zones.

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();

It's still not ideal though. We should have data and functions to cleanly support time zone selection.

I think this is a similar issue to #301. We may want to lean on the population data set for this filtering and make a dedicated api for it.

The population data is also what determines whether a timezone appears as a guess.

One note - TZDB frowns on actually using the time zone name for display to the end user. They recommend going through zone.tab or zone1970.tab with the descriptions. In practice I find this difficult, as the descriptions are inconsistent, and English only. I've been working on a blended approach with CLDR resource strings, but even that is difficult because CLDR places America/Denver and America/Phoenix both in "Mountain Time" - one has to hardcode an exception for "Mountain Time - Arizona" or similar - and the translations for that aren't necessarily available in the CLDR.

In general, time zone selection is a more difficult UX problem than it would seem.

I do like the map-based approach - though that's probably overkill for most solutions. I know of two:
https://github.com/dosx/timezone-picker
http://timezonepicker.com/

@mj1856 - is there any method/function to filter out these timezone and reduce the list close to 100-120 timezones?

We are converting an UTC timestamp to a deprecated timezone with Luxon and it gives us an invalid date. Is there no way of filtering the tz.names() call to only include non-deprecated timezones?
The timezone we used was Singapore instead of the available Asia/Singapore

We're also trying to generate a UX timezone picker, but the full output of tz.names() contains over 500 time zones, most of them deprecated. Would be great if moment-timezone could include an option to exclude them, or provide other useful subsets, like tz.names('common'). We don't expect many users from Antarctica for our app ;)

The workaround posted above doesn't work anymore as some of the data is an object.

There are deprecated timezones with slashes, for example 'US/Central', so we can't just filter by slash. Would be great to have additional fields in the tz db, deprecated, alias flags and the canonical name prop.

For example:

{
  "name": "US/Central",
  ...
  "deprecated": true,
  "canonical": "America/Chicago"
}

List of non-deprecated timezones really needed.

The valid ones are all "Continent/" or "Ocean/". I use this regex to only get those, and also include "UTC":

moment.tz.names().filter(tz => tz.match(/^(((Africa|America|Antarctica|Asia|Australia|Europe|Arctic|Atlantic|Indian|Pacific)\/.+)|(UTC))$/))

That takes it from 592 to 484 zones, but having an actual "deprecated" property would be better.

Also, being able to do filterYears() at runtime would be nice. I don't want to have to rebuild the library.

The above is incorrect, plenty of valid ones do not start with Continent/ or Ocean/ - UTC and GMT are a couple of examples of this.

I don't think this issue can be solved well with a regex, we need to just be able to pass an option to just get the current ones.

+1. I believe this is a feature to have. Otherwise, we have to manually filter the list of names using assumptions we are not qualified to come up with.

+1

This method gets you the "formal" (official), non backwards compatible names of timezones:

There are two different time zone databases commonly used in computing:

  • The Microsoft Windows Time Zone Database
  • The IANA/Olson Time Zone Database
    (Source: https://stackoverflow.com/tags/timezone/info)

If you consider the IANA Time Zone Database to be the official time zone database:

https://github.com/wlwl2/time-converter/tree/master/src/data

Replace zone1970.tab file with the latest zone1970.tab from https://www.iana.org/time-zones

Note: mine uses tzdb-2019c right now (the latest version still in April 2020) so you can just use the output file immediately: tz-and-comments-only-raw.js and no replacement is needed.

Run: node extract-tz-comments.js and you get the latest IANA Time Zone Database in the format:

[{"TZ":"Europe/Andorra","comments":""},{"TZ":"Asia/Dubai","comments":""},...]

In the output file in the same folder: tz-and-comments-only-raw.js or I guess you can rename it to .json. It is not pretty printed- data is in a single line right now.

If I remember correctly you can't use moment-timezone library for this: just use the official one. However it lacks some unofficial names people use in public (I intend to add this as a separate layer if I have time):

https://github.com/wlwl2/time-converter/issues/1

Oh I just realized this already covers Central, Mountain etc. in the comments (but these are unofficial I believe?), so that's why I included the comments key.

If anyone has time to help me compile a huge list like:

{ 
  location: 'Boston', 
  timeZone: 'America/New_York'
  ...
}

Create a new issue, PR or email me: https://github.com/wlwl2/time-converter/issues

FWIW the below gets me "close enough".

It seems that while moment.tz.names() doesn't take into account deprecated or links, moment.tz.zonesForCountry(X) does 🤷‍♂️

import moment from 'moment-timezone'

const zones = new Set()
const countries = moment.tz.countries()

for (const country of countries) {
  moment.tz.zonesForCountry(country).reduce((set, zone) => set.add(zone), zones)
}

export default [...zones].sort()

It seems that while moment.tz.names() doesn't take into account deprecated or links, moment.tz.zonesForCountry(X) does 🤷‍♂️

The quick explanation for this is that tz.names() returns every name found in the data _after_ processing all the links. Whereas tz.zonesForCountry() returns names defined in a separate part of the data, which directly mimics a specific file in the IANA source data: zone1970.tab.

Although there are still some links (incorrectly) hiding in the country data, by accident: #835. This also makes it harder to get the canonical zones from moment-timezone, because some of the links have been processed the wrong way around.

Was this page helpful?
0 / 5 - 0 ratings