Skip to content

Commit

Permalink
Merge pull request #229 from davec82/fix_occurrences_on_dst_transition
Browse files Browse the repository at this point in the history
fix: missing occurrences when there is a dst transition
  • Loading branch information
slvust committed Jan 3, 2024
2 parents 230963f + 7fee206 commit f3ea473
Show file tree
Hide file tree
Showing 3 changed files with 69 additions and 0 deletions.
24 changes: 24 additions & 0 deletions lib/cocktail/validation/shift.ex
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ defmodule Cocktail.Validation.Shift do
time
|> shift_time("#{type}": amount)
|> apply_option(option)
|> maybe_dst_change(time)

{:change, new_time}
end
Expand All @@ -29,4 +30,27 @@ defmodule Cocktail.Validation.Shift do
defp apply_option(time, :beginning_of_day), do: time |> beginning_of_day()
defp apply_option(time, :beginning_of_hour), do: %{time | minute: 0, second: 0, microsecond: {0, 0}}
defp apply_option(time, :beginning_of_minute), do: %{time | second: 0, microsecond: {0, 0}}

defp maybe_dst_change(%DateTime{} = new_time, %DateTime{} = time) do
dst_diff = new_time.std_offset - time.std_offset

case dst_diff do
0 ->
new_time

diff ->
maybe_shift_time(new_time, time, diff)
end
end

defp maybe_dst_change(new_time, _time), do: new_time

defp maybe_shift_time(new_time, time, dst_diff) do
shifted_time = shift_time(new_time, seconds: -dst_diff)

case DateTime.compare(shifted_time, time) do
:eq -> new_time
_ -> shifted_time
end
end
end
30 changes: 30 additions & 0 deletions test/cocktail/daily_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -163,4 +163,34 @@ defmodule Cocktail.DailyTest do
|> Cocktail.Schedule.occurrences(~N[2015-01-24 18:30:00])
|> Enum.take(100) == [~N[2015-01-24 18:30:00]]
end

test "generating occurrences with spring forward transition" do
schedule =
~Y[2022-03-12 18:00:00 America/Los_Angeles]
|> Schedule.new()
|> Schedule.add_recurrence_rule(:daily)

times = schedule |> Schedule.occurrences() |> Enum.take(3)

assert times == [
~Y[2022-03-12 18:00:00 America/Los_Angeles],
~Y[2022-03-13 18:00:00 America/Los_Angeles],
~Y[2022-03-14 18:00:00 America/Los_Angeles]
]
end

test "generating occurrences with fall back transition" do
schedule =
~Y[2022-11-05 18:00:00 America/Los_Angeles]
|> Schedule.new()
|> Schedule.add_recurrence_rule(:daily)

times = schedule |> Schedule.occurrences() |> Enum.take(3)

assert times == [
~Y[2022-11-05 18:00:00 America/Los_Angeles],
~Y[2022-11-06 18:00:00 America/Los_Angeles],
~Y[2022-11-07 18:00:00 America/Los_Angeles]
]
end
end
15 changes: 15 additions & 0 deletions test/cocktail/weekly_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -154,4 +154,19 @@ defmodule Cocktail.WeeklyTest do
~Y[2017-01-09 10:00:00 America/Los_Angeles]
]
end

test "Weekly with dst transition" do
times =
~Y[2022-03-12 06:00:00 America/Los_Angeles]
|> Cocktail.schedule()
|> Schedule.add_recurrence_rule(:weekly)
|> Cocktail.Schedule.occurrences()
|> Enum.take(3)

assert times == [
~Y[2022-03-12 06:00:00 America/Los_Angeles],
~Y[2022-03-19 06:00:00 America/Los_Angeles],
~Y[2022-03-26 06:00:00 America/Los_Angeles]
]
end
end

0 comments on commit f3ea473

Please sign in to comment.