CalDAVEx.Event (CalDAVEx v0.2.1)

Copy Markdown View Source

Event operations: listing, retrieval, and CRUD against a CalDAV calendar.

Listing uses the REPORT method with a calendar-query filter. Server-side recurrence expansion via <C:expand> is supported through the :expand_recurrences option on list/3.

Timed events whose DTSTART/DTEND carry a TZID parameter are normalized to UTC DateTime values using Tz.TimeZoneDatabase; ambiguous (fall-back) times resolve to the first occurrence and gap (spring-forward) times to the time immediately after the gap.

Summary

Types

Options accepted by list/3.

Keyword list of list_opt/0 values.

Functions

Creates a new event resource by PUTing iCalendar data to the calendar.

Deletes an event resource.

Fetches a single event resource by URL.

Lists events from a calendar, optionally filtered by a time range.

Replaces an existing event resource with new iCalendar data.

Types

list_opt()

@type list_opt() ::
  {:from, DateTime.t() | nil}
  | {:to, DateTime.t() | nil}
  | {:expand_recurrences, boolean()}

Options accepted by list/3.

list_opts()

@type list_opts() :: [list_opt()]

Keyword list of list_opt/0 values.

Functions

create(client, calendar_url, filename, ics_data)

@spec create(CalDAVEx.Client.t(), String.t(), String.t(), iodata()) ::
  {:ok, CalDAVEx.Types.Event.t()} | {:error, CalDAVEx.Error.t()}

Creates a new event resource by PUTing iCalendar data to the calendar.

The request includes If-None-Match: * to ensure the operation only succeeds when no resource exists at the target URL.

Parameters

  • client - an authenticated %CalDAVEx.Client{}
  • calendar_url - the URL of the parent calendar collection
  • filename - the resource filename (e.g. "event.ics")
  • ics_data - the iCalendar (VCALENDAR/VEVENT) body as a string

Returns

  • {:ok, %CalDAVEx.Types.Event{href: url}} on success
  • {:error, %CalDAVEx.Error{}} on failure

delete(client, event_url, etag)

@spec delete(CalDAVEx.Client.t(), String.t(), String.t() | nil) ::
  {:ok, CalDAVEx.HTTP.response()} | {:error, CalDAVEx.Error.t()}

Deletes an event resource.

When etag is provided, the request includes If-Match: <etag> for optimistic concurrency.

Parameters

  • client - an authenticated %CalDAVEx.Client{}
  • event_url - the full URL of the event resource
  • etag - the previously observed ETag, or nil to skip the conditional header

Returns

  • {:ok, %{status: non_neg_integer, body: term, headers: map}} on success
  • {:error, %CalDAVEx.Error{}} on HTTP, transport, or ETag-mismatch (412) failures

get(client, event_url)

@spec get(CalDAVEx.Client.t(), String.t()) ::
  {:ok, CalDAVEx.Types.Event.t()} | {:error, CalDAVEx.Error.t()}

Fetches a single event resource by URL.

Returns an event populated with the raw calendar_data body and the ETag header (when present). Parsed iCalendar fields such as summary or dtstart are not populated by this function; use list/3 for parsed results, or parse calendar_data yourself.

Parameters

  • client - an authenticated %CalDAVEx.Client{}
  • event_url - the full URL of the event resource

Returns

  • {:ok, %CalDAVEx.Types.Event{}} on success
  • {:error, %CalDAVEx.Error{}} on failure

list(client, calendar_url, opts \\ [])

@spec list(CalDAVEx.Client.t(), String.t(), list_opts()) ::
  {:ok, [CalDAVEx.Types.Event.t()]} | {:error, CalDAVEx.Error.t()}

Lists events from a calendar, optionally filtered by a time range.

Returned events are not guaranteed to be unique by href or etag: a single CalDAV resource whose calendar-data contains multiple VEVENT components (e.g. a recurring master plus RECURRENCE-ID overrides, or occurrences produced by <C:expand>) yields one %CalDAVEx.Types.Event{} per VEVENT sharing the same href/etag.

Parameters

  • client - an authenticated %CalDAVEx.Client{}
  • calendar_url - the full URL of the calendar collection
  • opts - keyword list:
    • :from - start of the time range (DateTime.t/0 or nil)
    • :to - end of the time range (DateTime.t/0 or nil)
    • :expand_recurrences - when true, asks the server to expand recurring events via <C:expand>. Both :from and :to MUST be provided when this is true; otherwise an {:error, %CalDAVEx.Error{type: :invalid_argument}} is returned. Server support varies. Defaults to false.

Returns

  • {:ok, [%CalDAVEx.Types.Event{}]} on success
  • {:error, %CalDAVEx.Error{}} on validation, transport, HTTP, or XML failures

Examples

{:ok, events} = CalDAVEx.Event.list(client, calendar.url,
  from: ~U[2025-05-01 00:00:00Z],
  to: ~U[2025-05-31 23:59:59Z]
)

update(client, event_url, ics_data, etag)

@spec update(CalDAVEx.Client.t(), String.t(), iodata(), String.t() | nil) ::
  {:ok, CalDAVEx.HTTP.response()} | {:error, CalDAVEx.Error.t()}

Replaces an existing event resource with new iCalendar data.

When etag is provided, the request includes If-Match: <etag> to perform an optimistic-concurrency update; a stale ETag results in a 412 HTTP error wrapped in CalDAVEx.Error.

Parameters

  • client - an authenticated %CalDAVEx.Client{}
  • event_url - the full URL of the event resource
  • ics_data - the replacement iCalendar body
  • etag - the previously observed ETag, or nil to skip the conditional header

Returns

  • {:ok, %{status: non_neg_integer, body: term, headers: map}} on success
  • {:error, %CalDAVEx.Error{}} on HTTP, transport, or ETag-mismatch (412) failures