A behaviour for providing the current time to Tempo.
All "now" queries in Tempo (Tempo.utc_now/0, Tempo.now/1,
Tempo.utc_today/0, Tempo.today/1) go through the clock
configured under :ex_tempo, :clock. The default is
Tempo.Clock.System, which delegates to DateTime.utc_now/0.
The indirection exists so tests can swap in a deterministic clock
without stubbing the Erlang system time. Tempo.Clock.Test is a
process-local stub suitable for ExUnit tests; see its module doc
for the usage pattern.
Configuring the clock
Application-wide default in config/test.exs:
config :ex_tempo, clock: Tempo.Clock.TestProcess-local override (safer in async: true ExUnit suites —
swaps the clock for the calling process only, leaving concurrent
tests and doctests with the default clock):
Process.put({Tempo.Clock, :clock}, Tempo.Clock.Test)In application code, use Tempo.utc_now/0 etc. rather than calling
the clock directly — the swap is transparent to callers.
Implementing a custom clock
A custom clock must return a DateTime.t/0. Implementations are
free to read from a database, a time-service mock, or a
distributed-system clock skew model. The one rule: the returned
DateTime must be in UTC (i.e. time_zone: "Etc/UTC", zero
offset). Zone projection happens downstream in Tempo.now/1.
Summary
Callbacks
Return the current UTC time as a DateTime.t/0 in Etc/UTC.
Callbacks
@callback utc_now() :: DateTime.t()
Return the current UTC time as a DateTime.t/0 in Etc/UTC.
Functions
@spec clock() :: module()
Return the currently configured clock module.
Looks first at Process.get({Tempo.Clock, :clock}) (the
process-local override used by ExUnit setups), then falls back to
Application.get_env(:ex_tempo, :clock), defaulting to
Tempo.Clock.System when neither is set.
The process-local override means tests that install
Tempo.Clock.Test do not leak that choice into unrelated
concurrent processes — a non-test doctest sharing the VM continues
to see the default system clock.
@spec utc_now() :: DateTime.t()
Return the current UTC time from the configured clock.
Delegates to the module configured under :ex_tempo, :clock,
defaulting to Tempo.Clock.System.