ExBooking.RRule (ExBooking v0.1.0)

View Source

Small RFC 5545 RRULE expander.

ExBooking.RRule supports a narrow dependency-free subset for common daily and weekly recurrences: FREQ, INTERVAL, COUNT, UTC UNTIL, and weekly BYDAY. Unsupported rule parts fail explicitly instead of being ignored.

Example

iex> {:ok, [first, second]} =
...>   ExBooking.RRule.expand(
...>     "FREQ=DAILY;COUNT=2",
...>     ~U[2026-07-13 09:00:00Z],
...>     30,
...>     ~U[2026-07-13 00:00:00Z],
...>     ~U[2026-07-15 00:00:00Z]
...>   )
...>
...> {first.start_at, second.start_at}
{~U[2026-07-13 09:00:00Z], ~U[2026-07-14 09:00:00Z]}

Summary

Types

Supported recurrence frequency.

t()

Parsed RRULE subset.

Functions

Expands rrule into UTC intervals over [from, until].

Parses an RFC 5545 RRULE line or value into the supported subset.

Types

frequency()

@type frequency() :: :daily | :weekly

Supported recurrence frequency.

t()

@type t() :: %ExBooking.RRule{
  byday: [1..7] | nil,
  count: pos_integer() | nil,
  freq: frequency(),
  interval: pos_integer(),
  until: DateTime.t() | nil
}

Parsed RRULE subset.

Functions

expand(rrule, dtstart, duration_min, from, until)

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

Expands rrule into UTC intervals over [from, until].

dtstart supplies the first occurrence start. duration_min supplies each occurrence duration. The returned intervals are sorted ascending.

Example

iex> {:ok, [first]} =
...>   ExBooking.RRule.expand(
...>     "FREQ=DAILY;COUNT=1",
...>     ~U[2026-07-13 09:00:00Z],
...>     30,
...>     ~U[2026-07-13 00:00:00Z],
...>     ~U[2026-07-14 00:00:00Z]
...>   )
...>
...> first.end_at
~U[2026-07-13 09:30:00Z]

parse(value)

@spec parse(String.t()) :: {:ok, t()} | {:error, term()}

Parses an RFC 5545 RRULE line or value into the supported subset.

Example

iex> {:ok, rule} = ExBooking.RRule.parse("FREQ=WEEKLY;BYDAY=MO,WE")
...> {rule.freq, rule.byday}
{:weekly, [1, 3]}