moment-timezone
moment-timezone copied to clipboard
Only "formal", non-backwards compatible names of timezones ?
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.. ?
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.