Skip to content

Commit

Permalink
Split interval and time modules
Browse files Browse the repository at this point in the history
  • Loading branch information
macobo committed Jul 3, 2024
1 parent 61ff043 commit d704b5b
Show file tree
Hide file tree
Showing 5 changed files with 278 additions and 269 deletions.
114 changes: 0 additions & 114 deletions lib/plausible/stats/interval.ex
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@ defmodule Plausible.Stats.Interval do
`week`, and `month`.
"""

alias Plausible.Stats.Query

@type t() :: String.t()
@type(opt() :: {:site, Plausible.Site.t()} | {:from, Date.t()}, {:to, Date.t()})
@type opts :: list(opt())
Expand Down Expand Up @@ -105,116 +103,4 @@ defmodule Plausible.Stats.Interval do
def valid_for_period?(period, interval, opts \\ []) do
interval in Map.get(valid_by_period(opts), period, [])
end

def format_datetime(%Date{} = date), do: Date.to_string(date)

def format_datetime(%DateTime{} = datetime),
do: Timex.format!(datetime, "{YYYY}-{0M}-{0D} {h24}:{m}:{s}")

# Realtime graphs return numbers
def format_datetime(other), do: other

@doc """
Returns list of time bucket labels for the given query.
"""
def time_dimension(query) do
Enum.find(query.dimensions, &String.starts_with?(&1, "time"))
end

def time_labels(query) do
time_labels_for_dimension(time_dimension(query), query)
end

defp time_labels_for_dimension("time:month", query) do
n_buckets =
Timex.diff(
query.date_range.last,
Date.beginning_of_month(query.date_range.first),
:months
)

Enum.map(n_buckets..0, fn shift ->
query.date_range.last
|> Date.beginning_of_month()
|> Timex.shift(months: -shift)
|> format_datetime()
end)
end

defp time_labels_for_dimension("time:week", query) do
n_buckets =
Timex.diff(
query.date_range.last,
Date.beginning_of_week(query.date_range.first),
:weeks
)

Enum.map(0..n_buckets, fn shift ->
query.date_range.first
|> Timex.shift(weeks: shift)
|> date_or_weekstart(query)
|> format_datetime()
end)
end

defp time_labels_for_dimension("time:day", query) do
query.date_range
|> Enum.into([])
|> Enum.map(&format_datetime/1)
end

@full_day_in_hours 23
defp time_labels_for_dimension("time:hour", query) do
n_buckets =
if query.date_range.first == query.date_range.last do
@full_day_in_hours
else
end_time =
query.date_range.last
|> Timex.to_datetime()
|> Timex.end_of_day()

Timex.diff(end_time, query.date_range.first, :hours)
end

Enum.map(0..n_buckets, fn step ->
query.date_range.first
|> Timex.to_datetime()
|> Timex.shift(hours: step)
|> DateTime.truncate(:second)
|> format_datetime()
end)
end

# Only supported in dashboards not via API
defp time_labels_for_dimension("time:minute", %Query{period: "30m"}) do
Enum.into(-30..-1, [])
end

@full_day_in_minutes 24 * 60 - 1
defp time_labels_for_dimension("time:minute", query) do
n_buckets =
if query.date_range.first == query.date_range.last do
@full_day_in_minutes
else
Timex.diff(query.date_range.last, query.date_range.first, :minutes)
end

Enum.map(0..n_buckets, fn step ->
query.date_range.first
|> Timex.to_datetime()
|> Timex.shift(minutes: step)
|> format_datetime()
end)
end

defp date_or_weekstart(date, query) do
weekstart = Timex.beginning_of_week(date)

if Enum.member?(query.date_range, weekstart) do
weekstart
else
date
end
end
end
6 changes: 3 additions & 3 deletions lib/plausible/stats/query_result.ex
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
defmodule Plausible.Stats.QueryResult do
@moduledoc false

alias Plausible.Stats.Interval
alias Plausible.Stats.Util
alias Plausible.Stats.Filters

Expand Down Expand Up @@ -49,7 +48,7 @@ defmodule Plausible.Stats.QueryResult do
defp dimension_label("time:" <> _ = time_dimension, entry, query) do
datetime = Map.get(entry, Util.shortname(query, time_dimension))

Interval.format_datetime(datetime)
Plausible.Stats.Time.format_datetime(datetime)
end

defp dimension_label(dimension, entry, query) do
Expand All @@ -72,7 +71,8 @@ defmodule Plausible.Stats.QueryResult do
:unsupported_query -> @imports_unsupported_query_warning
_ -> nil
end,
time_labels: if(query.include.time_labels, do: Interval.time_labels(query), else: nil)
time_labels:
if(query.include.time_labels, do: Plausible.Stats.Time.time_labels(query), else: nil)
}
|> Enum.reject(fn {_, value} -> is_nil(value) end)
|> Enum.into(%{})
Expand Down
118 changes: 118 additions & 0 deletions lib/plausible/stats/time.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
defmodule Plausible.Stats.Time do
@moduledoc """
Collection of functions to work with time in queries.
"""

alias Plausible.Stats.Query
def format_datetime(%Date{} = date), do: Date.to_string(date)

def format_datetime(%DateTime{} = datetime),
do: Timex.format!(datetime, "{YYYY}-{0M}-{0D} {h24}:{m}:{s}")

# Realtime graphs return numbers
def format_datetime(other), do: other

@doc """
Returns list of time bucket labels for the given query.
"""
def time_dimension(query) do
Enum.find(query.dimensions, &String.starts_with?(&1, "time"))
end

def time_labels(query) do
time_labels_for_dimension(time_dimension(query), query)
end

defp time_labels_for_dimension("time:month", query) do
n_buckets =
Timex.diff(
query.date_range.last,
Date.beginning_of_month(query.date_range.first),
:months
)

Enum.map(n_buckets..0, fn shift ->
query.date_range.last
|> Date.beginning_of_month()
|> Timex.shift(months: -shift)
|> format_datetime()
end)
end

defp time_labels_for_dimension("time:week", query) do
n_buckets =
Timex.diff(
query.date_range.last,
Date.beginning_of_week(query.date_range.first),
:weeks
)

Enum.map(0..n_buckets, fn shift ->
query.date_range.first
|> Timex.shift(weeks: shift)
|> date_or_weekstart(query)
|> format_datetime()
end)
end

defp time_labels_for_dimension("time:day", query) do
query.date_range
|> Enum.into([])
|> Enum.map(&format_datetime/1)
end

@full_day_in_hours 23
defp time_labels_for_dimension("time:hour", query) do
n_buckets =
if query.date_range.first == query.date_range.last do
@full_day_in_hours
else
end_time =
query.date_range.last
|> Timex.to_datetime()
|> Timex.end_of_day()

Timex.diff(end_time, query.date_range.first, :hours)
end

Enum.map(0..n_buckets, fn step ->
query.date_range.first
|> Timex.to_datetime()
|> Timex.shift(hours: step)
|> DateTime.truncate(:second)
|> format_datetime()
end)
end

# Only supported in dashboards not via API
defp time_labels_for_dimension("time:minute", %Query{period: "30m"}) do
Enum.into(-30..-1, [])
end

@full_day_in_minutes 24 * 60 - 1
defp time_labels_for_dimension("time:minute", query) do
n_buckets =
if query.date_range.first == query.date_range.last do
@full_day_in_minutes
else
Timex.diff(query.date_range.last, query.date_range.first, :minutes)
end

Enum.map(0..n_buckets, fn step ->
query.date_range.first
|> Timex.to_datetime()
|> Timex.shift(minutes: step)
|> format_datetime()
end)
end

defp date_or_weekstart(date, query) do
weekstart = Timex.beginning_of_week(date)

if Enum.member?(query.date_range, weekstart) do
weekstart
else
date
end
end
end
Loading

0 comments on commit d704b5b

Please sign in to comment.