ExBooking.Schedule (ExBooking v0.1.0)

View Source

Wall-time schedule expansion.

ExBooking.Schedule turns weekly windows, date overrides, and blackouts into concrete UTC intervals. It resolves ambiguous fall-back wall times to their first occurrence and snaps spring-forward gaps to the first valid instant after the gap.

Example

iex> rule = %ExBooking.AvailabilityRule{
...>   timezone: "Etc/UTC",
...>   windows: [%{weekday: 1, start_time: ~T[09:00:00], end_time: ~T[10:00:00]}]
...> }
...>
...> {:ok, [interval]} =
...>   ExBooking.Schedule.expand(rule, ~U[2026-07-13 00:00:00Z], ~U[2026-07-13 23:59:59Z])
...>
...> {interval.start_at, interval.end_at}
{~U[2026-07-13 09:00:00Z], ~U[2026-07-13 10:00:00Z]}

Summary

Functions

Expands a rule's weekly windows, overrides, and blackouts over [from, until] into merged, UTC-normalized offerable intervals.

Validates a rule's timezone and wall-time window shapes before expansion.

Functions

expand(rule, from, until)

@spec expand(ExBooking.AvailabilityRule.t(), DateTime.t(), DateTime.t()) ::
  {:ok, [ExBooking.Interval.t()]} | {:error, {:invalid, atom(), term()}}

Expands a rule's weekly windows, overrides, and blackouts over [from, until] into merged, UTC-normalized offerable intervals.

Examples

iex> rule = %ExBooking.AvailabilityRule{
...>   timezone: "Etc/UTC",
...>   windows: [%{weekday: 1, start_time: ~T[09:00:00], end_time: ~T[17:00:00]}]
...> }
...>
...> {:ok, [interval]} =
...>   ExBooking.Schedule.expand(rule, ~U[2026-07-13 00:00:00Z], ~U[2026-07-13 23:59:59Z])
...>
...> {interval.start_at, interval.end_at}
{~U[2026-07-13 09:00:00Z], ~U[2026-07-13 17:00:00Z]}

validate(rule)

@spec validate(ExBooking.AvailabilityRule.t()) ::
  :ok | {:error, {:invalid, atom(), term()}}

Validates a rule's timezone and wall-time window shapes before expansion.

Weekly windows require an ISO weekday and Time start/end values. Override windows require a Date plus Time start/end values. Invalid caller-built rules return stable tagged errors instead of raising during timezone or map access.

Example

iex> rule = %ExBooking.AvailabilityRule{timezone: "Etc/UTC", windows: []}
...> ExBooking.Schedule.validate(rule)
:ok