Tempo.RecurrenceSet (Tempo v2.1.1)

Copy Markdown View Source

A collection of rules whose occurrences form one set: a territory's public holidays, a calendar's events.

A recurrence set is a Tempo.t/0 of the :all form, so it goes where any expression goes: Tempo.to_interval/2 gives its occurrences within a window, and the set operations take it as an operand. Its members are recurrences (~o"R/../P1Y/FL12M25DN"), intervals and values, each with the metadata its occurrences carry (a holiday's name), and other sets.

A member may depend on the others. keep_when/2 keeps a member's occurrences only where the days around them fall on other members' occurrences (a bridge day), and move_when/2 moves an occurrence that falls on one (to the next Monday, say).

Summary

Functions

The set with the members a function is truthy for.

A member whose occurrences are kept only when the spans at given offsets from each fall on other members' occurrences: a bridge day between two holidays.

The members of a recurrence set, as they were given.

A member whose occurrence is moved when it falls on another member's occurrence: a holiday that gives way to another and is observed on the next Thursday.

Builds a recurrence set from its members.

new/2, returning the set or raising.

Functions

filter(set, fun)

@spec filter(Tempo.t(), (Tempo.t() -> as_boolean(term()))) :: Tempo.t()

The set with the members a function is truthy for.

Arguments

  • set is a recurrence set, a Tempo.t/0.

  • fun is given each member.

Returns

Examples

iex> set = Tempo.RecurrenceSet.new!([Tempo.put_metadata(~o"2026-12-25", %{type: :public}), ~o"2026-01-01"])
iex> set |> Tempo.RecurrenceSet.filter(&(Tempo.metadata(&1)[:type] == :public)) |> Tempo.RecurrenceSet.members() |> length()
1

keep_when(member, options)

@spec keep_when(Tempo.t(), keyword()) :: Tempo.t()

A member whose occurrences are kept only when the spans at given offsets from each fall on other members' occurrences: a bridge day between two holidays.

Arguments

  • member is a Tempo.t/0: a recurrence, an interval or a value.

  • options is a keyword list of options.

Options

  • :at is a list of Tempo.Duration.t/0 offsets from an occurrence's start (~o"-P1D" is the day before); every one must fall on an occurrence. Required.

  • :falls_on is a map another member's occurrence must hold in its metadata (%{type: :public}), or a Tempo.t/0 whose spans are read instead. Required.

  • :metadata is a map every occurrence of the member carries.

Returns

  • A Tempo.t/0 of the :when form, for a set to hold.

Examples

iex> bridge = Tempo.RecurrenceSet.keep_when(~o"2026-09-22", at: [~o"-P1D", ~o"P1D"], falls_on: %{type: :public})
iex> {:ok, holidays} =
...>   Tempo.RecurrenceSet.new([
...>     Tempo.put_metadata(~o"2026-09-21", %{type: :public}),
...>     Tempo.put_metadata(~o"2026-09-23", %{type: :public}),
...>     bridge
...>   ])
iex> {:ok, days} = Tempo.to_interval(holidays)
iex> Tempo.IntervalSet.map(days, &Tempo.day/1)
[21, 22, 23]

members(set)

@spec members(Tempo.t()) :: [Tempo.t()]

The members of a recurrence set, as they were given.

Arguments

  • set is a recurrence set, or a rule on its own, a Tempo.t/0.

Returns

Examples

iex> Tempo.RecurrenceSet.members(Tempo.RecurrenceSet.new!([~o"2026-12-25", ~o"2026-01-01"]))
[~o"2026-12-25", ~o"2026-01-01"]

move_when(member, options)

@spec move_when(Tempo.t(), keyword()) :: Tempo.t()

A member whose occurrence is moved when it falls on another member's occurrence: a holiday that gives way to another and is observed on the next Thursday.

Arguments

  • member is a Tempo.t/0: a recurrence, an interval or a value.

  • options is a keyword list of options.

Options

  • :falls_on is as for keep_when/2. Required.

  • :to_next is a selector for Tempo.select/3 (~o"1K", Monday): the occurrence moves to the first span it gives after the occurrence. Required.

  • :metadata is a map every occurrence of the member carries.

Returns

  • A Tempo.t/0 of the :when form, for a set to hold.

Examples

iex> moved = Tempo.RecurrenceSet.move_when(~o"2026-04-09", falls_on: %{type: :observance}, to_next: ~o"4K")
iex> {:ok, holidays} = Tempo.RecurrenceSet.new([Tempo.put_metadata(~o"2026-04-09", %{type: :observance}), moved])
iex> {:ok, days} = Tempo.to_interval(holidays)
iex> Tempo.IntervalSet.map(days, &Tempo.day/1)
[9, 16]

new(members, options \\ [])

@spec new([Tempo.t()], keyword()) :: {:ok, Tempo.t()} | {:error, Exception.t()}

Builds a recurrence set from its members.

Arguments

  • members is a list of Tempo.t/0: recurrences, intervals, values, sets, and the conditional members keep_when/2 and move_when/2 build.

  • options is a keyword list of options.

Options

  • :metadata is a map the set carries.

Returns

  • {:ok, set}, a Tempo.t/0 of the :all form.

  • {:error, exception} when the members are of several calendars.

Examples

iex> {:ok, holidays} = Tempo.RecurrenceSet.new([~o"R/2026-01-01/P1Y/FL12M25DN", ~o"R/2026-01-01/P1Y/FL1M1DN"])
iex> {:ok, days} = Tempo.to_interval(holidays, within: ~o"2026")
iex> Tempo.IntervalSet.map(days, &Tempo.month/1)
[1, 12]

new!(members, options \\ [])

@spec new!([Tempo.t()], keyword()) :: Tempo.t()

new/2, returning the set or raising.

Arguments

  • members and options are as for new/2.

Options

Returns

Examples

iex> Tempo.RecurrenceSet.new!([~o"2026-12-25"]) |> Tempo.RecurrenceSet.members() |> length()
1