diff --git a/lib/tzdata.ex b/lib/tzdata.ex index 5507873..379f620 100644 --- a/lib/tzdata.ex +++ b/lib/tzdata.ex @@ -241,7 +241,8 @@ defmodule Tzdata do defp possible_periods_for_zone_and_time(zone_name, time_point, time_type) do {:ok, periods} = Tzdata.ReleaseReader.periods_for_zone_time_and_type(zone_name, time_point, time_type) mapped_periods = periods - |> Enum.sort_by(fn {_, from_utc, _, _, _, _, _, _, _, _} -> -(from_utc |> Tzdata.ReleaseReader.delimiter_to_number) end) + |> Tzdata.ReleaseReader.sort_periods() + |> Enum.reverse |> Enum.map( fn {_, f_utc, f_wall, f_std, u_utc, u_wall, u_std, utc_off, std_off, zone_abbr} -> %{ diff --git a/lib/tzdata/release_reader.ex b/lib/tzdata/release_reader.ex index 1189bb5..1102427 100644 --- a/lib/tzdata/release_reader.ex +++ b/lib/tzdata/release_reader.ex @@ -43,8 +43,7 @@ defmodule Tzdata.ReleaseReader do defp do_periods_for_zone(zone) do case lookup_periods_for_zone(zone) do periods when is_list(periods) -> - periods - |> Enum.sort_by(fn period -> elem(period, 1) |> delimiter_to_number() end) + sort_periods(periods) _ -> nil @@ -57,18 +56,31 @@ defmodule Tzdata.ReleaseReader do defp lookup_periods_for_zone(_), do: [] @doc !""" - Hack which is useful for sorting periods. Delimiters can be integers representing - gregorian seconds or :min or :max. By converting :min and :max to integers, they are - easier to sort. It is assumed that the fake numbers they are converted to are far beyond - numbers used. TODO: Instead of doing this, do the sorting before inserting. When reading from a bag the order should be preserved. """ - @very_high_number_representing_gregorian_seconds 9_315_537_984_000 - @low_number_representing_before_year_0 -1 - def delimiter_to_number(:min), do: @low_number_representing_before_year_0 - def delimiter_to_number(:max), do: @very_high_number_representing_gregorian_seconds - def delimiter_to_number(integer) when is_integer(integer), do: integer + def sort_periods(periods), do: Enum.sort(periods, &periods_ordered?/2) + + defp periods_ordered?( + {_, _, _, _, _, _, _, _, _, _}, + {_, :min, _, _, _, _, _, _, _, _} + ), + do: false + + defp periods_ordered?( + {_, :max, _, _, _, _, _, _, _, _}, + {_, _, _, _, _, _, _, _, _, _} + ), + do: false + + defp periods_ordered?( + {_, left, _, _, _, _, _, _, _, _}, + {_, right, _, _, _, _, _, _, _, _} + ) + when is_integer(left) and is_integer(right) and left > right, + do: false + + defp periods_ordered?(_, _), do: true defp current_release_from_table do :ets.lookup(:tzdata_current_release, :release_version) |> hd |> elem(1)