A session that repeats — a weekly stand-up, a fortnightly clinic, a daily hand-over.
A series is not a new kind of thing. Expanding one gives back
ordinary sessions, each windowed to one occurrence, so everything
that works on a session works on every occurrence: planning,
arranging, allocating, explaining. What they share is a :series
name, which is what lets the whole run be released together — or
released from a date forward, leaving the past alone.
The recurrence itself is Tempo's, so ISO 8601 (R10/2027-03-02T09:00:00/P1W)
and RFC 5545 (FREQ=WEEKLY;COUNT=10) both work, and both expand
correctly across daylight saving.
Example
iex> standup = Agenda.session("Stand-up", duration: "PT15M")
iex> {:ok, occurrences} = Agenda.every(standup, "R3/2027-03-02T09:00:00/P1W")
iex> Enum.map(occurrences, & &1.name)
["Stand-up 1", "Stand-up 2", "Stand-up 3"]
iex> import Tempo.Sigils
iex> standup = Agenda.session("Stand-up", duration: "PT15M")
iex> {:ok, [first | _]} = Agenda.every(standup, "R3/2027-03-02T09:00:00/P1W")
iex> {first.series, first.window}
{"Stand-up", ~o"2027Y3M2DT9H0M0S/9DT9H0M0S"}"The stand-up repeats weekly three times; the first occurrence may fall anywhere in the week beginning the 2nd of March."
Summary
Functions
Expand session over pattern, one occurrence per repetition.
Functions
@spec expand(Agenda.Session.t(), Agenda.Availability.pattern(), keyword()) :: {:ok, [Agenda.Session.t()]} | {:error, term()}
Expand session over pattern, one occurrence per repetition.
Each occurrence is a full session whose window is that repetition's span, so an occurrence can be planned, moved, or refused on its own.
Arguments
sessionis theAgenda.Session.t/0to repeat. Its own window, if any, is replaced by each occurrence's.patternis a recurrence — an ISO 8601 repeating interval (preferred) or an RFC 5545RRULE.
Options
:boundbounds an otherwise unbounded recurrence. Required whenpatterndoes not state its own count or end.
Returns
{:ok, sessions}, one per occurrence, in time order; or{:error, reason}when the pattern cannot be read or is unbounded and unbounded by:bound.
Examples
iex> clinic = Agenda.session("Clinic", duration: "PT4H")
iex> {:ok, occurrences} = Agenda.Series.expand(clinic, "R2/2027-03-02/P1D")
iex> length(occurrences)
2
iex> clinic = Agenda.session("Clinic", duration: "PT4H")
iex> Agenda.Series.expand(clinic, "not a recurrence")
{:error, :unreadable_pattern}