Skip to main content

ical

PyPI version Python versions CI Documentation

A modern Python RFC 5545 iCalendar library with built-in recurring event support — no companion libraries needed.

from ical.calendar_stream import IcsCalendarStream

cal = IcsCalendarStream.calendar_from_ics(ics_content)

# Recurring events are automatically expanded — just iterate
for event in cal.timeline:
    print(event.start, event.summary)

Why ical?

Most Python iCalendar libraries require two separate packages to handle recurring events:

# The typical ecosystem approach — two libraries, two APIs
import icalendar
import recurring_ical_events

cal = icalendar.Calendar.from_ical(ics_content)
events = recurring_ical_events.of(cal).between(start, end)

ical handles this natively with a single, unified Timeline interface, built on a fully type-safe Pydantic v2 data model.

Feature ical icalendar ics.py
Built-in recurrence expansion ❌ needs recurring-ical-events
Pydantic v2 data model
Full type annotations (py.typed) ✅ strict mypy ✅ v7+
Application-level store API
RFC 7986 / RFC 6868 / RFC 8536 partial
Active maintenance ⚠️ stalled

Used By

Installation

pip install ical

Requires Python 3.11+.

Quickstart

Reading an .ics file

Parse a calendar file and iterate over events in chronological order, with recurring events automatically expanded:

from pathlib import Path
from ical.calendar_stream import IcsCalendarStream
from ical.exceptions import CalendarParseError

filename = Path("calendar.ics")
with filename.open() as ics_file:
    try:
        cal = IcsCalendarStream.calendar_from_ics(ics_file.read())
    except CalendarParseError as err:
        print(f"Failed to parse '{filename}': {err}")
    else:
        for event in cal.timeline:
            print(event.start, event.summary)

Creating a calendar

from datetime import date
from ical.calendar import Calendar
from ical.event import Event

cal = Calendar()
cal.events.append(
    Event(summary="Team standup", start=date(2024, 1, 15), end=date(2024, 1, 16)),
)
for event in cal.timeline:
    print(event.summary)

Writing an .ics file

from pathlib import Path
from ical.calendar_stream import IcsCalendarStream

with Path("output.ics").open("w") as f:
    f.write(IcsCalendarStream.calendar_to_ics(cal))

Recurring events

Recurring events are stored once in the calendar but automatically expanded by the Timeline:

from datetime import date
from ical.calendar import Calendar
from ical.event import Event
from ical.types.recur import Recur

cal = Calendar()
cal.events.append(
    Event(
        summary="Weekly standup",
        start=date(2024, 1, 15),
        end=date(2024, 1, 16),
        rrule=Recur.from_rrule("FREQ=WEEKLY;COUNT=10"),
    )
)

# All 10 occurrences are expanded automatically
for event in cal.timeline:
    print(event.start, event.summary)

Application-level API

For managing calendar state in an application (ensuring timezones are set correctly, editing individual instances of recurring events, etc.), use ical.store:

from ical.store import EventStore
from ical.event import Event
from datetime import datetime, timezone

store = EventStore()
store.add(Event(summary="Meeting", start=datetime(2024, 1, 15, 9, tzinfo=timezone.utc)))

See the full documentation for the complete API reference.

Supported RFCs

  • RFC 5545 — Internet Calendaring and Scheduling Core Object Specification (iCalendar)
  • RFC 6868 — Parameter Value Encoding in iCalendar and vCard
  • RFC 7986 — New Properties for iCalendar
  • RFC 8536 — The Time Zone Information Format (TZif)

Comparison with other libraries

ical is designed for applications that need a complete, modern solution. You may prefer an alternative if:

  • icalendar — You need low-level control over raw iCalendar components, jCal (JSON) support, or maximum ecosystem compatibility. You prefer to expand recurring events manually and don't mind a second library (recurring-ical-events). You need to support legacy Python versions (3.8+) that ical does not target.
  • ics.py — You need a simple read-only script and do not require recurrence support. Note: no stable release since 0.7.2 (August 2021).

Contributing

See CONTRIBUTING.md for setup and development instructions.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

ical-14.0.0.tar.gz (148.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

ical-14.0.0-py3-none-any.whl (139.9 kB view details)

Uploaded Python 3

File details

Details for the file ical-14.0.0.tar.gz.

File metadata

  • Download URL: ical-14.0.0.tar.gz
  • Upload date:
  • Size: 148.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ical-14.0.0.tar.gz
Algorithm Hash digest
SHA256 675c619fff68af665894932f79cec5b53f43afce36a2379d945916f7adb3fca4
MD5 ee77aeac6926f62d04e6a2fb5ff3110a
BLAKE2b-256 845b0c0dfbf68b7f698243535e692f999b94f99d2cd3bfb8bc4bcac7d6513c0b

See more details on using hashes here.

Provenance

The following attestation bundles were made for ical-14.0.0.tar.gz:

Publisher: publish.yaml on allenporter/ical

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file ical-14.0.0-py3-none-any.whl.

File metadata

  • Download URL: ical-14.0.0-py3-none-any.whl
  • Upload date:
  • Size: 139.9 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for ical-14.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 ae5eeb82e044da1a9bb689225bccaefc4ba9eaa049adfa4f3b5179a67f81f105
MD5 311a9c115f69154401a9b4d25f490213
BLAKE2b-256 96b2a6281456a263a95929453da11b9b135ac0c49f91fd67dd6435a1f5d250b2

See more details on using hashes here.

Provenance

The following attestation bundles were made for ical-14.0.0-py3-none-any.whl:

Publisher: publish.yaml on allenporter/ical

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page