I’ve explored two approaches for getting Time.Zone values to use with elm/time, both of which use the IANA Time Zone Database (TZ).
To be clear, the use case is that you have Posix values and you want to extract parts from them in some local time, not just UTC.
Often you have UTC timestamps that you just need to display nicely formatted in the client’s local time zone. For this, it’s possible to push the job out to custom elements, like Github’s time-elements.
The following, however, are ways of getting time zone data into Elm.
1. Fetch only the zone data you need at runtime
Since Elm targets web browsers, this seems a natural fit.
The timezone-json repo contains a script you can use to build a set of JSON files from (the compiled artifacts of) the TZ database. It also contains Elm examples of fetching and decoding them to Time.Zone values.
2. Include the time zone database in your compiled asset
This sounds a little crazy, but I can imagine use cases for this, and once minified and gzipped it only adds 18 KB.
The timezone-data package allows this. Data in the package is generated by a script that converts (the source files of) the TZ database to Elm source; each zone must be “unpacked” to get a Time.Zone value. The unpacked Time.Zone values match exactly those built from the timezone-json approach above.
With both of these, the Time.Zone values only cover changes between 1970 and 2037.
Each of the links above should contain examples to get you started, but please let me know if you have questions.
I really like what you’ve done here! I’ve been using elm-community/elm-time, but I’m working on using the timezone-data for my upgraded 0.19 app.
There are two things that I can’t figure out how to do between this library and the core Time:
Get the zone name (ie America/Chicago) for a given time zone (I only see a way to do it for my timezone)
Get the zone abbreviation (CDT or CST) for a given zone and time
Do you see these as being handled by your library in the future or in a separate package? I don’t know if it’s possible to add the name and abbreviations in the same way that it was handled in elm-time or not.
Again, thank you for working on this problem as well as the Date package!
The Zone in elm/time doesn’t store a zone name (e.g. America/Chicago). But the TimeZone.getZone task returns the local zone name too so that you can store it if you’d like to. And if you happen to get zone names at runtime in some other way, then you can look up zone data in the TimeZone.Data.packs dictionary. In these cases you already have the zone name, so it’s not essential that Zone store a name.
And Zone doesn’t store zone abbreviation (e.g. CST, CDT) changes. The goal of this library was to provide Zone values, so it’s not something I had yet considered handling in another way.
Can I ask, why is there a Pack type at all? (It doesn’t seem to be used for anything except unpacking?) Why doesn’t TimeZone.Data.* just give the Zones? (Or possibly all be () -> Zone to avoid compuation/memory usage?)
Also, looking at the elm/time API, it looks like there’s no function to get all the human info at once (toYear/toMonth/toDay/… are all separate functions). Doesn’t that mean that if you want to show all fields it’s doing a lot of duplicate work to process the Zone?
That’s a great idea to use thunks to simplify the API. Right, the reason for Pack was to avoid the cost of unpacking hundreds of Zones on page load, but you’re right, each zone could simply be a () -> Zone function instead. I’m glad you asked!
And yes, if you get N parts from the same Zone and Posix, then the offset is looked up from the Zone N times. Currently that lookup involves scanning an ordered list of transition times until a time < the posix time is found.