> ## Documentation Index
> Fetch the complete documentation index at: https://super-calendar.afonsojramos.me/llms.txt
> Use this file to discover all available pages before exploring further.

# iCalendar (.ics) import & export

> Read and write RFC 5545 .ics files so events interoperate with Google, Apple, and Outlook.

`@super-calendar/core` ships `parseICalendar` and `toICalendar` to convert between
`.ics` text and the library's `CalendarEvent` shape — so a calendar built with
super-calendar can import feeds from, and export to, Google Calendar, Apple
Calendar, Outlook, and anything else that speaks iCal.

```ts theme={null}
import { parseICalendar, toICalendar } from "@super-calendar/core";
// also re-exported from "@super-calendar/dom" and "@super-calendar/native"
```

## Import

`parseICalendar(text)` returns an array of events you can pass straight to a
`<Calendar>`:

```ts theme={null}
const res = await fetch("/calendar.ics");
const events = parseICalendar(await res.text());

// -> [{ uid, title, start, end, allDay?, description?, location?, recurrence? }]
```

Each event carries the standard fields it round-trips: `uid`, `description`,
`location`, plus `allDay` (from `VALUE=DATE`) and a `recurrence` parsed from
`RRULE`. Recurring events are returned as a single event with a rule — expand them
for a date range with [`expandRecurringEvents`](/guides/recurring-events):

```ts theme={null}
import { expandRecurringEvents, parseICalendar } from "@super-calendar/core";

const occurrences = expandRecurringEvents(parseICalendar(ics), rangeStart, rangeEnd);
```

## Export

`toICalendar(events)` produces a complete `VCALENDAR` string. Timed events are
written in UTC; set `allDay: true` for `VALUE=DATE` events; a `recurrence` becomes
an `RRULE`.

```ts theme={null}
const ics = toICalendar(events);

// Offer it as a download in the browser:
const url = URL.createObjectURL(new Blob([ics], { type: "text/calendar" }));
```

Pass `{ prodId, now }` to set the calendar's `PRODID` and the `DTSTAMP` written on
each event. A stable `UID` is derived from the event when you don't supply one, so
re-exports stay diff-friendly.

## What's covered

A pragmatic subset of RFC 5545, aimed at real-world event interchange:

* **`VEVENT`** with `SUMMARY`, `DESCRIPTION`, `LOCATION`, `UID`, `DTSTART`, and either
  `DTEND` or `DURATION` (e.g. `PT1H30M`, `P1D`).
* **All-day** events via `VALUE=DATE` (a missing end becomes a one-day span).
* **Dates** in UTC (`...Z`), a named IANA zone (`TZID=Europe/London`, resolved to
  the correct instant), floating local, or date-only; line folding and text
  escaping per the spec.
* **`RRULE`** round-tripped to a [`RecurrenceRule`](/guides/recurring-events)
  (`FREQ`, `INTERVAL`, `COUNT`, `UNTIL`, weekly `BYDAY`, and ordinal `BYDAY` like
  `3MO`/`-1FR` → `nthWeekday`), plus **`EXDATE`** exception days
  (`recurrence.exdates`, honoured by `expandRecurringEvents`).

Not (yet) handled: `VTODO` / `VJOURNAL`, `VALARM`, attendees, attachments, and
embedded `VTIMEZONE` definitions (a `TZID` must be a valid IANA name for the
runtime's `Intl`). Contributions welcome.
