Tempo.ICal (Tempo v0.5.0)

Copy Markdown View Source

Import iCalendar (RFC 5545) data into %Tempo.IntervalSet{}.

This module wraps the ical parser and translates each VEVENT into a %Tempo.Interval{} with full event metadata (summary, description, location, attendees, status, …) attached to the interval's :metadata map. The VCALENDAR envelope's metadata (product id, version, calendar scale, method) attaches to the IntervalSet's :metadata map.

Every pipeline step that accepts a Tempo value — set operations, Enum.take/2, resolution alignment — preserves the metadata through to the result. That lets free/busy and scheduling queries stay connected to their source events.

The ical dependency is declared optional: true in mix.exs. Tempo.ICal is only compiled when ical is available in the dependency tree; projects that don't import calendar data don't pay the compile cost.

Required reading

  • RFC 5545 — the iCalendar spec.
  • guides/set-operations.md for how the imported data is used downstream.

RFC 5545 coverage

PropertyStatus
RRULEFully supported — every BY* part, WKST, and
BYSETPOS flow through the interpreter.
RDATESupported — extra occurrences with the event's
own span.
EXDATESupported — start-moment match removes the
corresponding occurrence.
EXRULENot surfaced by the underlying ical library, so
not implementable at this layer. EXRULE is also
RFC-deprecated (RFC 2445 → 5545).
MultipleRFC 5545 says SHOULD NOT; some exports do it
RRULEanyway. The ical library exposes only the
perfirst RRULE on event.rrule, so we materialise
VEVENTthat one and silently ignore the rest.

Summary

Functions

Parse an iCalendar string and return a %Tempo.IntervalSet{}.

Parse an iCalendar file and return a %Tempo.IntervalSet{}.

Functions

from_ical(ics, opts \\ [])

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

Parse an iCalendar string and return a %Tempo.IntervalSet{}.

Every VEVENT becomes one %Tempo.Interval{} in the result. All-day events (DTSTART as a Date) use day-resolution endpoints; datetime events use the matching datetime resolution. The event's SUMMARY, DESCRIPTION, LOCATION, UID, STATUS, TRANSPARENCY, CATEGORIES, attendees, and organizer all flow into the interval's :metadata map.

The calendar-level metadata (PRODID, VERSION, CALSCALE, METHOD, and the user-visible name from X-WR-CALNAME when present) attaches to the IntervalSet's :metadata map.

Arguments

  • ics is an iCalendar string (the contents of an .ics file).

Options

  • :bound — a Tempo.t/0, Tempo.Interval.t/0, or Tempo.IntervalSet.t/0 within which recurring events (those with an RRULE) are expanded. Required when any event in the input has a recurrence rule; ignored when there are none. An unbounded recurrence is infinite and refused at set-op time.

Returns

  • {:ok, interval_set} — sorted, coalesced IntervalSet of the events.
  • {:error, reason} when parsing fails or a recurring event requires a :bound that wasn't supplied.

Examples

iex> ics = """
...> BEGIN:VCALENDAR
...> VERSION:2.0
...> PRODID:-//Test//Test//EN
...> BEGIN:VEVENT
...> UID:test-1
...> DTSTAMP:20220101T000000Z
...> DTSTART:20220615T100000Z
...> DTEND:20220615T110000Z
...> SUMMARY:Test meeting
...> LOCATION:Paris
...> END:VEVENT
...> END:VCALENDAR
...> """
iex> {:ok, set} = Tempo.ICal.from_ical(ics)
iex> length(set.intervals)
1
iex> [iv] = set.intervals
iex> iv.metadata.summary
"Test meeting"
iex> iv.metadata.location
"Paris"

from_ical_file(path, opts \\ [])

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

Parse an iCalendar file and return a %Tempo.IntervalSet{}.

Wraps from_ical/2 with File.read/1.

Arguments

  • path is a path to an .ics file.

Options

See from_ical/2.

Returns

  • {:ok, interval_set} or {:error, reason}.