Elixir relies on third-party libraries to bring in time zone support.
Below are some available options:
tz
time_zone_info
tzdata
zoneinfo
- recommended for embedded devices
This repository allows to perform time zone operations on a huge set of predefined date times, for each of the libraries listed above, and compare their result.
Generate the result for Java by executing GenerateTzData.java
in /java
.
The result is written in /files/output
.
Execute the mix task to generate the result for the Elixir libraries:
mix tzdb.run tz
mix tzdb.run time_zone_info
mix tzdb.run zoneinfo
mix tzdb.run tzdata
The result is written in /files/output
.
Use your favorite diff tool to compare the result between the output of the libraries and Java. I consider the Java output the source of truth.
At the time of writing this,
- the output of Java,
tz
andtime_zone_info
is identical; tzdata
generates a lot of wrong dates;zoneinfo
generates wrong dates for some special time zones and for dates in the year 2038.
Time spent generating the result is logged in the console, giving some idea of the difference in terms of performance.
The time taken for each library to generate the output on my system are:
- ~50 seconds for
tz
- ~50 seconds for
time_zone_info
- ~80 seconds for
zoneinfo
- ~160 seconds for
tzdata
System used:
- Operating system: macOS
- CPU: Apple M2
- Available cores: 8
- Available memory: 16 GB
- Elixir version: 1.14.1
- Erlang version: 25.1.2
Predefined dates, against which time zone operations are tested, are located in /files/input
.
Those dates include a lot of dates for which edge cases can be found (ambiguous times, gaps, etc.).
The input files list 51,112 dates.
Example entry:
America/Curacao;1912-02-11
For each of these dates, the program generates 96 date times. The first date time starts at midnight and is increased by a step of 15 minutes until 23:45.
This results in 4,906,752 (51,112 x 96) date times generated
Then for each date time, the following operations are performed:
- Adds the time zone information to the naive date time
DateTime.from_naive(naive_date_time, timezone)
- Shifts the utc date time to the time zone
naive_date_time
|> DateTime.from_naive!("Etc/UTC")
|> DateTime.shift_zone(timezone)
That makes for a total of 9,813,504 date times being generated.
The date times are written into files which can be compared between the different libraries (using a diff tool) to detect any errors and inconsistencies.