Call for proposals: time zone support in Elixir

I am looking forward to having this behaviour in the Elixir standard library - something that has been planned for a long time, and I think there was even talk about having it in Elixir version 1.4 or 1.5.

This sounds like it is based on a misunderstanding.

The Tzdata library has a bunch of different public functions. However they are not all needed to simply do timezone calculations. For instance you can get a list of all time zones, which is useful in some situations. But for the core calculations you mostly need one function.

Example:

gregorian_seconds = {{2018,01,01},{00,00,00}} |> :calendar.datetime_to_gregorian_seconds()
periods = Tzdata.periods_for_time("Europe/Copenhagen", gregorian_seconds, :wall)

Since there is no ambiguity for that wall time this returns just one period which has the abbreviation, standard offset and UTC offset needed to make a DateTime struct.

Here a behaviour that is not released, but one that the Tzdata library implements:

  @type gregorian_seconds :: non_neg_integer()
  @type time_zone_period_limit :: gregorian_seconds() | :min | :max
  @type time_zone_period :: %{
          utc_off: Calendar.utc_offset(),
          std_off: Calendar.standard_offset(),
          zone_abbr: Calendar.zone_abbr(),
          from: %{
            standard: time_zone_period_limit,
            utc: time_zone_period_limit,
            wall: time_zone_period_limit
          },
          until: %{
            standard: time_zone_period_limit,
            utc: time_zone_period_limit,
            wall: time_zone_period_limit
          }
        }

  @callback periods_for_time(Calendar.time_zone(), gregorian_seconds, :wall | :utc) :: [
              time_zone_period
            ] | {:error, :not_found}

Both Tzdata 0.1.x and 0.5.x versions implement that behaviour. So you can either have the newer version that can update automatically or the 0.1.x versions that require manual updates.

The “from” and “until” part are useful when there is a gap in wall time during e.g. “spring forward”. The “standard” part is not needed for most calculations, and I would lean towards excluding the “standard” part of from/until from a native Elixir behaviour.

0.1.x versions of Tzdata are using compilation of the data using macros. Once compiled and loaded, it is quite fast. The negative part of that is memory usage during compilation, but more importantly it requires compiling again whenever new data is needed. Akin to recompiling Postgrex everytime someone writes to a Postgres database.

About leap seconds: I also think there should be an interface/behaviour for that. Either as the same behaviour or one separate for one for time zones. Leap seconds are needed in order to verify UTC datetimes. So in order to fully support ISO8601 and UTC they are needed. And the tz database from IANA has leap second information included, so if we want to support both UTC and timezones, it makes sense to not ignore the leap second information provided.

4 Likes