Parse any calendar format#

This chapter describes how to parse calendar data when you don't know in advance whether it's iCalendar, jCal, or xCal.

icalendar supports three calendar formats, each with its own parser:

The function parse() detects the format for you and calls the matching parser.

Parse bytes#

Pass the data as bytes.

>>> from icalendar import parse
>>> data = b'["vcalendar", [["prodid", {}, "text", "example"]], []]'
>>> calendar = parse(data)
>>> calendar["PRODID"]
vText(b'example')

The format is detected from the first character, ignoring whitespace and a byte order mark:

  • B or b, as in BEGIN:VCALENDAR, means iCalendar.

  • [ means jCal.

  • < means xCal.

The data is passed to the parser unchanged, so parse() accepts what the matching parser accepts.

If the format can't be detected, parse() raises UnknownCalendarFormat.

>>> parse(b"not a calendar")
Traceback (most recent call last):
  ...
icalendar.error.UnknownCalendarFormat: Could not detect the calendar format: expected iCal, jCal, or xCal data, but the data starts with b'not a cale'.

Parse a file#

Pass a Path to read and parse a file.

>>> from pathlib import Path
>>> calendar = parse(Path("src/icalendar/tests/calendars/example.ics"))
>>> len(calendar.events)
3

Alternatively, pass a file opened in binary mode.

>>> with open("src/icalendar/tests/calendars/example.ics", "rb") as file:
...     calendar = parse(file)
>>> len(calendar.events)
3

A file opened in text mode returns str instead of bytes, so parse() raises a TypeError.

Parse several calendars#

iCalendar and xCal data may contain several calendars. jCal data always contains one calendar. Most data contains only one calendar.

By default, parse() returns one calendar. If the data contains more than one calendar, returning only one of them would lose the others, so it raises CalendarInformationLost. If the data contains no calendars, it raises NoCalendarsFound.

To get all calendars as a list, pass multiple=True.

The example below demonstrates the iCalendar stream. The ical variable contains only one calendar. ical + ical parses into two calendars.

>>> ical = b"BEGIN:VCALENDAR\r\nPRODID:example\r\nEND:VCALENDAR\r\n"
>>> calendars = parse(ical + ical, multiple=True)
>>> len(calendars)
2