mathieuprog / tz

Time zone support for Elixir
Apache License 2.0
125 stars 11 forks source link

Overload the timezone format for local mean time #3

Closed tjheeta closed 3 years ago

tjheeta commented 3 years ago

Thanks for the library. I've been using this patch for over 6 months for LMT by overloading the timezone with the longitude.

A timezone of "Europe/Brussels" would then become "Europe/Brussels|-13".

If the timezone returned is LMT and the longitude exists, we adjust the timezone offset appropriately accounting for the longitude.

mathieuprog commented 3 years ago

Hi! I've never seen a format such as "Europe/Brussels|-13". Is this standard? Do other languages accept this time zone identifier format? Does Java support this?

tjheeta commented 3 years ago

As far as I know, no, to all questions, however, patch is backwards compatible.

Without this patch, any date shifts/additions from local mean time (LMT) to a modern timezone are incorrect as the offset would not have been calculated at all. The same is true for any LMT date comparisons, etc.

Essentially, every LMT time has the incorrect offset without accounting for the longitude.

The format appends the longitude to the timezone to ensure the information is embedded. This was the easiest way I could think of to ensure the correctness of the standard Elixir DateTime functions after consulting the core elixir list.

This library is the most correct one I found, so I patched it to get the correct times for older dates.

mathieuprog commented 3 years ago

I think that you should wrap Tz time zone database, to make your own time zone database implementation.

@behaviour Calendar.TimeZoneDatabase

@impl true
def time_zone_period_from_utc_iso_days(iso_days, time_zone) do
  {time_zone, longitude} = parse_time_zone_longitude(time_zone)

  Tz.time_zone_period_from_utc_iso_days(iso_days, time_zone)
  |> apply_longitude_if_lmt(longitude)
end

@impl true
def time_zone_periods_from_wall_datetime(naive_datetime, time_zone) do
  {time_zone, longitude} = parse_time_zone_longitude(time_zone)

  Tz.time_zone_periods_from_wall_datetime(naive_datetime, time_zone)
  |> apply_longitude_if_lmt(longitude)
end

As this is non-standard, I prefer not to integrate it into Tz directly. A wrapper should cover your needs.