Tempo.RRule.Rule (Tempo v0.5.0)

Copy Markdown View Source

A canonical, typed representation of an RFC 5545 RRULE.

This is the input to Tempo.RRule.Expander.expand/3. Every parser (Tempo.RRule.parse/2, the ical library's %ICal.Recurrence{}, hand-built rules for tests) converts to this shape before expansion runs. Keeping a single struct means the expander has one input vocabulary to match against, and all BY* fields carry their RFC-typed form: lists of integers with negative values permitted where the RFC allows.

Fields

  • :freq — one of :second, :minute, :hour, :day, :week, :month, :year. Required.

  • :interval — positive integer multiplier for the frequency. Default 1.

  • :count — terminate after this many occurrences. Mutually exclusive with :until per RFC 5545.

  • :until — terminate at or before this Tempo.t/0. Mutually exclusive with :count.

  • :wkst — week-start day as an integer 1–7 (Monday–Sunday, ISO convention). Default 1. Affects :byweekno calculations.

  • :bymonth — list of integers 1–12. Limit.

  • :bymonthday — list of integers -31..31 (negatives count from the end of the month). Limit or expand per FREQ.

  • :byyearday — list of integers -366..366. Limit or expand per FREQ.

  • :byweekno — list of integers -53..53. Used only with :yearly FREQ. Limit or expand.

  • :byday — list of {ordinal_or_nil, weekday_1_to_7} tuples. With MONTHLY / YEARLY and no BYWEEKNO, ordinals select the Nth/-Nth weekday within the period. With other FREQs, ordinals are ignored (filter only).

  • :byhour / :byminute / :bysecond — lists of integers. Limit or expand per FREQ.

  • :bysetpos — list of integers; applied last to pick the Nth element of the per-period candidate set.

Summary

Functions

Does the rule include any BY* modifier?

Types

byday_entry()

@type byday_entry() :: {integer() | nil, weekday()}

frequency()

@type frequency() :: :second | :minute | :hour | :day | :week | :month | :year

t()

@type t() :: %Tempo.RRule.Rule{
  byday: [byday_entry()] | nil,
  byhour: [non_neg_integer()] | nil,
  byminute: [non_neg_integer()] | nil,
  bymonth: [integer()] | nil,
  bymonthday: [integer()] | nil,
  bysecond: [non_neg_integer()] | nil,
  bysetpos: [integer()] | nil,
  byweekno: [integer()] | nil,
  byyearday: [integer()] | nil,
  count: pos_integer() | nil,
  freq: frequency(),
  interval: pos_integer(),
  until: Tempo.t() | nil,
  wkst: weekday()
}

weekday()

@type weekday() :: 1..7

Functions

has_by_rules?(rule)

@spec has_by_rules?(t()) :: boolean()

Does the rule include any BY* modifier?

true when any BY* field is non-nil. Used by the expander to skip the BY-rule pipeline entirely for simple FREQ-only rules.

Examples

iex> Tempo.RRule.Rule.has_by_rules?(%Tempo.RRule.Rule{freq: :weekly})
false

iex> Tempo.RRule.Rule.has_by_rules?(%Tempo.RRule.Rule{freq: :weekly, byday: [{nil, 1}]})
true