Tempo.RRule.Selection (Tempo v0.5.0)

Copy Markdown View Source

Resolve RRULE BY* selection tokens during recurrence expansion.

Called from Tempo.to_interval/2's recurrence loop. Given a candidate occurrence and a repeat_rule whose :time carries a [{:selection, [...]}] keyword list (the shared AST produced by Tempo.RRule.parse/2 and Tempo.RRule.Expander.to_ast/3), decide whether the candidate is kept, dropped, or expanded into multiple occurrences.

Implemented rules

Per RFC 5545 §3.3.10's EXPAND/LIMIT table:

PartRole and when
BYMONTHLIMIT — always.
BYMONTHDAYLIMIT — any FREQ except WEEKLY (forbidden).
BYYEARDAYLIMIT — any FREQ coarser than DAILY.
BYWEEKNOLIMIT — YEARLY only.
BYDAY (no ordinal)LIMIT for DAILY/HOURLY/MINUTELY/SECONDLY;
EXPAND within the enclosing week/month/year for
WEEKLY, MONTHLY, YEARLY.
BYDAY (with ordinal)EXPAND — pairs (ordinal, weekday) like
1MO and -1FR pick the Nth / Nth-from-last
matching weekday within the enclosing period
(month for MONTHLY, year for YEARLY). Backed by
Calendrical.Kday.nth_kday/3.
BYHOUREXPAND when FREQ is coarser than hour; LIMIT
when FREQ is hour-or-finer.
BYMINUTESame pattern at the minute unit.
BYSECONDSame pattern at the second unit.
BYSETPOSLIMIT — applied last, across the post-filter
per-period candidate set. Negative values count
from the end (-1 = last).

Tokens this module doesn't interpret pass through unchanged so partial support is correct for the partial inputs.

Summary

Functions

Apply a repeat_rule to one candidate occurrence and return the resulting list of occurrences.

Functions

apply(candidate, repeat_rule, freq)

@spec apply(Tempo.Interval.t(), Tempo.t() | nil, atom()) :: [Tempo.Interval.t()]

Apply a repeat_rule to one candidate occurrence and return the resulting list of occurrences.

Arguments

  • candidate is a Tempo.Interval.t/0 — the current occurrence under consideration.

  • repeat_rule is either nil (no rule — passthrough) or a %Tempo{} whose :time holds [selection: [...]].

  • freq is the enclosing FREQ atom (:second, :minute, :hour, :day, :week, :month, :year). Drives the EXPAND-vs-LIMIT dispatch for rules whose role depends on the enclosing frequency.

Returns

  • A list of Tempo.Interval.t/0 occurrences — [] on LIMIT rejection, [candidate] on passthrough or LIMIT accept, [c1, c2, …] on EXPAND.

Examples

iex> candidate = %Tempo.Interval{from: ~o"2022-06-15", to: ~o"2022-06-16"}
iex> rule = %Tempo{time: [selection: [month: 6]], calendar: Calendrical.Gregorian}
iex> Tempo.RRule.Selection.apply(candidate, rule, :month)
[candidate]

iex> candidate = %Tempo.Interval{from: ~o"2022-07-15", to: ~o"2022-07-16"}
iex> rule = %Tempo{time: [selection: [month: 6]], calendar: Calendrical.Gregorian}
iex> Tempo.RRule.Selection.apply(candidate, rule, :month)
[]