Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion lib/tzdata.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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} ->
%{
Expand Down
34 changes: 23 additions & 11 deletions lib/tzdata/release_reader.ex
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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)
Expand Down