Tempo.RRule (Tempo v0.5.0)

Copy Markdown View Source

Parses iCalendar RFC 5545 RRULE strings into Tempo AST (%Tempo.Interval{} with a %Tempo.Duration{} cadence and, where needed, a repeat_rule built from selection tokens).

This module is intentionally small — it exists to validate that Tempo's AST is a sufficient target for recurrence rules expressed in formats other than ISO 8601-2. See docs/rrule-ast-validation.md for findings.

Supported rule parts

  • FREQSECONDLY | MINUTELY | HOURLY | DAILY | WEEKLY | MONTHLY | YEARLY

  • INTERVAL — positive integer, default 1

  • COUNT — positive integer (mutually exclusive with UNTIL)

  • UNTIL — basic-format ISO 8601 date or date-time

  • BYMONTH, BYMONTHDAY, BYYEARDAY, BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND — comma-separated (optionally negative) integer list

  • BYDAY — comma-separated list where each entry is [<sign><ordinal>]<weekday> (e.g. MO, -1FR, 4TH)

  • BYSETPOS — comma-separated integer list

  • WKST — weekday code

Returns

{:ok, %Tempo.Interval{}} on success.

Examples

iex> {:ok, %Tempo.Interval{} = i} = Tempo.RRule.parse("FREQ=DAILY;COUNT=10")
iex> {i.recurrence, i.duration.time}
{10, [day: 1]}

iex> {:ok, i} = Tempo.RRule.parse("FREQ=WEEKLY;INTERVAL=2;UNTIL=20221231")
iex> i.duration.time
[week: 2]

Summary

Functions

Parse an RRULE string into a %Tempo.Interval{} AST node.

Functions

parse(rrule, options \\ [])

@spec parse(
  binary(),
  keyword()
) :: {:ok, Tempo.Interval.t()} | {:error, term()}

Parse an RRULE string into a %Tempo.Interval{} AST node.

Arguments

  • rrule is a string in RRULE form (with or without the leading RRULE: prefix).

Options

  • :from — a %Tempo{} anchor (DTSTART). Sets Interval.from so occurrence enumeration has a starting point. Optional; callers that intend to enumerate must supply this.

Returns

  • {:ok, %Tempo.Interval{}} on success.

  • {:error, reason} on a malformed rule or unknown keyword.

Examples

iex> {:ok, i} = Tempo.RRule.parse("FREQ=DAILY;COUNT=10")
iex> i.recurrence
10

iex> {:error, _} = Tempo.RRule.parse("FREQ=NOPE")

parse!(rrule, options \\ [])

@spec parse!(
  binary(),
  keyword()
) :: Tempo.Interval.t()

Bang variant of parse/2.