ExBooking.Slotting (ExBooking v0.1.0)

View Source

Candidate slot generation.

Slotting cuts free intervals into bookable starts. Duration controls how long each slot is; step controls how often starts are offered. The default grid starts at the free interval boundary, while align: :clock snaps to UTC clock boundaries such as :00, :15, :30, and :45.

Example

iex> free = ExBooking.Interval.new!(~U[2026-07-13 09:00:00Z], ~U[2026-07-13 10:00:00Z])
...> free |> ExBooking.Slotting.generate_slots(30, 15) |> Enum.map(& &1.start_at)
[~U[2026-07-13 09:00:00Z], ~U[2026-07-13 09:15:00Z], ~U[2026-07-13 09:30:00Z]]

Summary

Functions

Generates slots across many free intervals, deduplicated and sorted.

Generates candidate slots of duration_min minutes on a step_min grid anchored to the free interval's start by default.

Functions

generate_all(free_intervals, duration_min, step_min, opts \\ [])

@spec generate_all([ExBooking.Interval.t()], pos_integer(), pos_integer(), keyword()) ::
  [
    ExBooking.Interval.t()
  ]

Generates slots across many free intervals, deduplicated and sorted.

Duplicate starts can occur when free intervals from different sources overlap after DST normalization; the first occurrence wins.

Examples

iex> a = ExBooking.Interval.new!(~U[2026-07-13 09:00:00Z], ~U[2026-07-13 09:30:00Z])
...> b = ExBooking.Interval.new!(~U[2026-07-13 09:00:00Z], ~U[2026-07-13 09:30:00Z])
...> ExBooking.Slotting.generate_all([a, b], 30, 30) |> length()
1

generate_slots(free, duration_min, step_min, opts \\ [])

@spec generate_slots(ExBooking.Interval.t(), pos_integer(), pos_integer(), keyword()) ::
  [
    ExBooking.Interval.t()
  ]

Generates candidate slots of duration_min minutes on a step_min grid anchored to the free interval's start by default.

Options:

  • :align:free_start (default) or :clock

Every returned slot fits entirely inside free and carries kind: :available. Returns slots sorted ascending by start.

Examples

iex> free = ExBooking.Interval.new!(~U[2026-07-13 09:00:00Z], ~U[2026-07-13 10:00:00Z])
...> slots = ExBooking.Slotting.generate_slots(free, 30, 15)
...> Enum.map(slots, & &1.start_at)
[~U[2026-07-13 09:00:00Z], ~U[2026-07-13 09:15:00Z], ~U[2026-07-13 09:30:00Z]]

iex> free = ExBooking.Interval.new!(~U[2026-07-13 09:00:00Z], ~U[2026-07-13 09:20:00Z])
...> ExBooking.Slotting.generate_slots(free, 30, 15)
[]