iCalendar
icalendar is an RFC 5545 compatible parser and generator of iCalendar files. It facilitates the creation, modification, and parsing of calendar data (events, todos, journals) in Python. The library is actively maintained with frequent patch releases within major versions, and new major versions are released occasionally to introduce breaking changes and new features.
Warnings
- breaking In v7.0.0, the `from_ical` method on `Calendar`, `Event`, and other components now expects a string (`str`) or bytes (`bytes`) object directly, instead of a file-like object.
- breaking Version 7.0.0 introduced significant changes to how datetime objects are handled, aligning more strictly with Python's standard `datetime` module. Floating datetimes (without `tzinfo`) are now treated as UTC by default if no `TZID` is specified.
- gotcha Incorrect timezone handling is a common source of errors. If datetimes are not timezone-aware, `icalendar` might make assumptions (e.g., UTC) that don't match your intended local time.
- breaking In v5.0.0, `vDDDTypes` (used for date/datetime/duration properties) is no longer directly callable. Instead, you must use its static methods `vDDDTypes.from_str()` for parsing and `vDDDTypes.to_ical()` for serialization.
Install
-
pip install icalendar
Imports
- Calendar
from icalendar import Calendar
- Event
from icalendar import Event
- vRecur
from icalendar import vRecur
- vDDDTypes
from icalendar import vDDDTypes
Quickstart
import datetime
from icalendar import Calendar, Event, vRecur
# --- Create an iCalendar ---
cal = Calendar()
cal.add('prodid', '-//My Organisation//Example Calendar App//EN')
cal.add('version', '2.0')
event = Event()
event.add('summary', 'Team Standup')
# Always use timezone-aware datetimes for iCalendar
event.add('dtstart', datetime.datetime(2024, 7, 10, 9, 0, 0, tzinfo=datetime.timezone.utc))
event.add('dtend', datetime.datetime(2024, 7, 10, 9, 15, 0, tzinfo=datetime.timezone.utc))
event.add('dtstamp', datetime.datetime.now(datetime.timezone.utc))
event['uid'] = 'event_20240710_standup@example.com'
event.add('location', 'Online Meeting Room')
# Add a recurrence rule (e.g., daily for 5 occurrences)
rrule = vRecur({'freq': ['DAILY'], 'count': [5]})
event.add('rrule', rrule)
cal.add_component(event)
# Serialize to iCalendar format
ical_string = cal.to_ical().decode('utf-8')
print("--- Generated iCalendar ---")
print(ical_string)
# --- Parse an iCalendar ---
print("\n--- Parsed iCalendar ---")
parsed_cal = Calendar.from_ical(ical_string)
for component in parsed_cal.walk():
if component.name == 'VEVENT':
print(f"Summary: {component.get('summary')}")
print(f"Start: {component.get('dtstart').dt}")
print(f"End: {component.get('dtend').dt}")
if 'rrule' in component:
print(f"Recurrence Rule: {component.get('rrule')}")