Skip to content
Merged
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
18 changes: 16 additions & 2 deletions lib/plausible/stats/comparisons.ex
Original file line number Diff line number Diff line change
Expand Up @@ -156,14 +156,28 @@ defmodule Plausible.Stats.Comparisons do
defp get_comparison_datetime_range(
%Query{
input_date_range: input_range,
include: %{compare: :year_over_year}
include: %{compare: :year_over_year} = include
} = source_query
)
when input_range in [:"24h", :day] do
comparison_start = DateTime.shift(source_query.utc_time_range.first, year: -1)
comparison_end = DateTime.shift(source_query.utc_time_range.last, year: -1)

DateTimeRange.new!(comparison_start, comparison_end)
if include.compare_match_day_of_week do
source_first_date = Times.to_date(source_query.utc_time_range.first, source_query.timezone)
comparison_first_date = Times.to_date(comparison_start, source_query.timezone)

day_to_match = Date.day_of_week(source_first_date)
matched_date = shift_to_nearest(day_to_match, comparison_first_date, source_first_date)
days_shifted = Date.diff(matched_date, comparison_first_date)

DateTimeRange.new!(
DateTime.shift(comparison_start, day: days_shifted),
DateTime.shift(comparison_end, day: days_shifted)
)
else
DateTimeRange.new!(comparison_start, comparison_end)
end
end

defp get_comparison_datetime_range(
Expand Down
77 changes: 77 additions & 0 deletions test/plausible/stats/comparisons_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,65 @@ defmodule Plausible.Stats.ComparisonsTest do
|> Enum.count()
end

describe "with period set to today" do
test "handles YoY comparison mode matching exact date", %{site: site} do
query =
QueryBuilder.build!(site,
metrics: [:visitors],
input_date_range: :day,
include: [compare: :year_over_year],
now: ~U[2023-03-15 18:30:00Z]
)

comparison_query = Comparisons.get_comparison_query(query)

assert comparison_query.utc_time_range.first == ~U[2022-03-15 00:00:00Z]
assert comparison_query.utc_time_range.last == ~U[2022-03-15 18:30:00Z]
end

test "handles YoY comparison mode with match_day_of_week enabled",
%{site: site} do
query =
QueryBuilder.build!(site,
metrics: [:visitors],
input_date_range: :day,
include: [compare: :year_over_year, compare_match_day_of_week: true],
now: ~U[2023-03-15 18:30:00Z]
)

comparison_query = Comparisons.get_comparison_query(query)

# today range: 2023-03-15 (Wednesday) 00:00:00 to 18:30:00 UTC
# Year ago: 2022-03-15 (Tuesday); nearest Wednesday is 2022-03-16 (+1 day)
assert comparison_query.utc_time_range.first == ~U[2022-03-16 00:00:00Z]
assert comparison_query.utc_time_range.last == ~U[2022-03-16 18:30:00Z]
end

test "handles YoY + match_day_of_week comparison for a non-UTC timezone" do
site = insert(:site, timezone: "US/Eastern")

# 2023-03-14 20:30:00 (Tuesday) in US/Eastern
utc_now = ~U[2023-03-15 00:30:00Z]

query =
QueryBuilder.build!(site,
metrics: [:visitors],
input_date_range: :day,
include: [compare: :year_over_year, compare_match_day_of_week: true],
now: utc_now
)

comparison_query = Comparisons.get_comparison_query(query)

# Year ago: March 14, 2022 is Monday
# Nearest Tuesday: March 15, 2022 (+1 day)
# Comparison start in US/Eastern: 2022-03-15T00:00:00
assert comparison_query.utc_time_range.first == ~U[2022-03-15 04:00:00Z]
# Comparison end in US/Eastern: 2022-03-15T20:30:00
assert comparison_query.utc_time_range.last == ~U[2022-03-16 00:30:00Z]
end
end

describe "with period set to 24h" do
test "shifts back 24h period when mode is previous_period", %{site: site} do
query =
Expand Down Expand Up @@ -477,6 +536,24 @@ defmodule Plausible.Stats.ComparisonsTest do
assert comparison_query.utc_time_range.last == ~U[2022-03-15 18:30:00Z]
end

test "handles YoY with match_day_of_week enabled", %{site: site} do
query =
QueryBuilder.build!(site,
metrics: [:visitors],
input_date_range: :"24h",
include: [compare: :year_over_year, compare_match_day_of_week: true],
now: ~U[2023-03-15 18:30:00Z]
)

comparison_query = Comparisons.get_comparison_query(query)

# Main 24h range: 2023-03-14 18:30:00 (Tue) -> 2023-03-15 18:30:00 (Wed)
# Year ago: 2022-03-14 18:30:00 (Mon) -> 2022-03-15 18:30:00 (Tue)
# Nearest Tuesday to Monday: March 15, 2022 (+1 day shift)
assert comparison_query.utc_time_range.first == ~U[2022-03-15 18:30:00Z]
assert comparison_query.utc_time_range.last == ~U[2022-03-16 18:30:00Z]
end

test "custom time zone works with 24h comparison" do
site = insert(:site, timezone: "US/Eastern")

Expand Down
Loading