Library / SDK
collective/icalendar avatar
collective/icalendar

icalendar: an RFC 5545 parser and generator for Python

icalendar parser library for Python

1,187 stars518 forksPythonBSD-2-Clause

At a glance

What is it?
icalendar reads, inspects and writes iCalendar files in Python, with support for zoneinfo, dateutil and pytz timezones. It is the base layer that several other calendaring packages build on, and its own scope stops at the file format rather than at queries, recurrence expansion or sync.
Who is it for?
Adopt icalendar if you need to read, write or modify iCalendar files in Python and want a standards focused parser with real timezone handling rather than a home grown one, and if you are willing to take the surrounding layer from the ecosystem, since recurrence expansion and date queries belong to iCalEvents and recurring-ical-events and server side sync belongs to caldav.
Can I use it commercially?
Yes. BSD-2-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Python, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 6, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • collective/icalendar1,187 ★ · +0
Star history
Repository2026-10-232026-11-06
collective/icalendar1.2k1.2k

0 Stars in the last 14 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

The file format is the scope

icalendar is a Python package for the Internet Calendaring and Scheduling format, iCalendar. The package description is precise about what it is: an RFC 5545 compatible parser and generator of iCalendar files, and a tool to create, inspect and modify calendaring information with Python.

That word, compatible, does the work. The library is not an implementation of somebody's calendar dialect, it targets the standard, which matters when the files come from a variety of clients that each interpret parts of the specification slightly differently. A parser that follows the RFC tends to survive contact with real calendars better than one that models a particular product.

The object model follows the format itself, which means the components a file contains are the components you get. The package keywords give the scope: calendar, calendaring, ical, icalendar, event, todo, journal, recurring, rfc5545. An event, a to-do entry, a journal entry and a VALARM are all first class rather than being special cases bolted on afterwards.

The project is a collective one. The author field in the package metadata is the Plone Foundation, there are four named maintainers, and the funding route is Open Collective. Documentation lives on Read the Docs, the source is at github.com/collective/icalendar, and there is a Matrix chat for the package and a second one for the wider PyCal community.

The dependency list is short: python-dateutil and tzdata. That is worth pausing on, because timezone data is where calendar libraries usually accumulate a pile of transitive dependencies.

Timezone handling is the part that decides your integration

icalendar supports multiple timezone implementations: zoneinfo from the standard library, dateutil.tz, and pytz. The choice is yours, and the same library can be used with whichever one your application already runs on.

This matters more than it first appears, because a calendar library that mishandles timezones produces bugs that look like data corruption. An event stored in one zone and displayed in another, a recurrence that crosses a daylight saving boundary, a VTIMEZONE component that a consumer cannot interpret: all of these are decided by the timezone layer, and all of them are much cheaper to get right when you reuse an existing implementation.

The tzdata dependency is the belt to that pair of braces. On systems where the operating system does not ship a current IANA database, tzdata is the package that keeps zoneinfo accurate, and the library depends on it explicitly rather than leaving you to discover a stale database in production.

The related project x-wr-timezone deserves a mention here, because it addresses a specific real-world annoyance. It is a library and command line tool that makes icalendar.Calendar objects and files from Google Calendar using the non-standard X-WR-TIMEZONE property, while staying compliant with RFC 5545. Google Calendar writes that property and other clients ignore it, so a converter that understands it produces files that display correctly in more places. That is the kind of gap this ecosystem fills with small, focused packages.

The other direction of support is for privacy rather than compatibility. icalendar-anonymizer strips personal data from iCalendar files while preserving the technical properties, which is what you want when you need a reproducible bug report without handing over your attendees' details.

Where the ecosystem splits the work

The related projects list in the README is the clearest picture of how the pieces fit together, and it is worth reading as a dependency map rather than as a list of alternatives.

iCalEvents is built on top of icalendar and lets you query iCalendar files to get the events happening on specific dates, and it manages recurrent events as well. recurring-ical-events does the same job for an icalendar.Calendar object, for events and other components happening at a certain date or within a certain time. ics-query is the command line version of that idea, a tool to query iCalendar files for occurrences of events and other components. So the split is clean: icalendar owns the format, and the query layer lives on top of it.

caldav is a CalDAV client library, an RFC 4791 implementation, built on icalendar. That is the piece you add when the calendar is on a server rather than in a file, and it is deliberately a separate package, so the base library stays free of any network code.

The genuine alternative in the list is VObject, which the README describes as intended to be a full-featured Python package for parsing and generating Card and Calendar files. The difference in approach is scope. VObject treats vCard and vCalendar as one package, while icalendar is focused on the iCalendar format alone and is at its most useful when you want the structure of the file rather than a general object graph over a contact card and a calendar. If your data includes address books, VObject is the one to evaluate.

Two more sit at the edges. ical2jcal converts between iCalendar and jCalendar, and sphinx-icalendar provides calendar code blocks and syntax highlighting in a tabbed interface for documentation, as a Sphinx extension. icalendar-compatibility gives access to event data across different implementations, and the Python Calendaring Ecosystem project at pycal.org collects the standards compliant packages.

Package metadata and the compatibility floor

The packaging tells you how the project is run, and it is modern in the ways that matter for a library you will depend on.

The build backend is hatchling with hatch-vcs, and the version is listed as dynamic because it is generated from the version control tag rather than written into the file by hand. That is the arrangement that avoids a release forgetting to bump a number. The project name is icalendar, the description is RFC 5545 compatible parser and generator of iCalendar files, and the readme is README.rst with content type text/x-rst.

requires-python is >=3.10, and the Makefile pins the working range as >=3.10,<3.15. The comment block in the package file is worth reading if you contribute, because it lists everything that has to be touched when the supported Python version changes: the two GitHub Actions workflows, the classifiers, two documentation pages, the dependency list, the Ruff target version, a file called compatibility.py and the Makefile itself. That is the kind of checklist that shows a project has learned from doing it once.

The classifier list includes Development Status:: 5 - Production/Stable, and the code is laid out under src/ with the package data described in MANIFEST.in.

The tooling is worth noting as well. The Makefile drives documentation builds with Sphinx, and it pulls in Ruff, Vale with a.vale.ini, and Zizmor, with their options variables in the same file. The docs build runs with warnings treated as errors through the -W flag. Pre-commit is configured in.pre-commit-config.yaml, and tox.ini is there for running tests across environments.

The licence is a two-clause BSD licence, named in the README and declared in the package metadata as BSD-2-Clause with LICENSE.rst as the licence file. Note that GitHub's own classifier reports the repository as having a custom licence it cannot categorise, so the LICENSE.rst file and the package metadata are what to rely on.

How the development loop is wired

The contributor experience is described by the Makefile more than by prose, and it is coherent.

The.venv target installs the pinned Python version with uv, creates the virtual environment, syncs the dependencies including the dev group, and installs the pre-commit hooks. The sync target does the dependency sync alone, init chains clean, clean-python and.venv, and clean removes the docs build directory, and clean-python additionally removes the virtual environment. Environment management is done with uv rather than a mixture of tools, which keeps the setup in one place.

The change log is managed with towncrier, and the TOWNCRIERPATH variable in the Makefile points at it. That is consistent with the news/ directory at the repository root, which is where towncrier expects the per-change fragment files to live, and with CHANGES.rst at the root as the rendered result. The project uses the fragment-per-change convention rather than asking contributors to edit a single changelog file, which is why the news directory is in the tree.

The documentation is a Sphinx project under docs/, published to Read the Docs, with the how-to section covering how to read, modify and write iCalendar files. The README itself is an index that points at that guide rather than duplicating it, and it also points at the install page, the contribution guide, the discussions board, the issue tracker and the changelog reference.

The README is deliberately reStructuredText, with a title, a metadata block and badges. It ends with the related projects, the change log pointer and the funding and chat links, so the whole document is a map rather than a manual.

Maintenance, security and what to check before you upgrade

The project is not archived, and the last push was on 2026-10-15. The release line is active, with v7.2.1 and v7.2.2 both tagged on 2026-07-20 and v7.3.0 on 2026-08-19. Two releases on the same day, followed by a feature release about four weeks later, is a project with a regular release rhythm rather than one that ships when someone gets around to it.

There is a SECURITY.md in the repository, which is the place to look for how the project handles a reported vulnerability. A parser that reads files from other people is exactly the kind of code where a malformed input should be reported rather than filed as a bug, and having the policy written down is a sign the maintainers thought about it.

The version number is the thing to watch. This is a 7.x line, and a major version in a library like this usually means interface changes in the object model rather than a rewrite of the internals. The upgrade documentation is one of the pages the project explicitly tells you to update when the Python version changes, which suggests there is real guidance for moving between versions rather than a changelog and nothing else.

What the library will not do is worth stating, because it is where people get disappointed. It does not fetch calendars from a server, since CalDAV is a separate package. It does not expand recurring events into occurrences for you, since that is iCalEvents and recurring-ical-events. It does not handle vCard address books, since that is VObject's territory. And it does not do anything with a jCalendar file, since that is the ical2jcal conversion.

Within those boundaries it is a well maintained, standards focused library with a small dependency footprint, a real test and linting setup, and a documentation site that explains how to use it.

Editorial conclusion

Adopt icalendar if you need to read, write or modify iCalendar files in Python and want a standards focused parser with real timezone handling rather than a home grown one, and if you are willing to take the surrounding layer from the ecosystem, since recurrence expansion and date queries belong to iCalEvents and recurring-ical-events and server side sync belongs to caldav. Do not adopt it if you need vCard support, because the file format is its boundary, or if you need a hosted calendar service, because this is a library with no network layer. Before you start, read the usage guide in the documentation rather than the README, since the README is an index, decide which timezone implementation your deployment will use, and check the changelog when upgrading across minor versions, because the project is on a 7.x line with frequent releases.

Frequently asked questions

What is icalendar used for in Python?

It is an RFC 5545 compatible parser and generator of iCalendar files, so you can create, inspect and modify calendaring information in Python. Events, to-dos, journal entries and alarms are all first class components, and the package is on PyPI as icalendar.

Which timezone implementations does icalendar support?

It supports zoneinfo from the standard library, dateutil.tz and pytz, so you can use whichever one your application already runs on. The package also depends on tzdata, which keeps the IANA database current on systems that do not ship one.

How do I query a calendar for events on a given date with icalendar?

That is the job of the layers built on top of it. iCalEvents is built on icalendar and lets you query iCalendar files for the events happening on specific dates, managing recurrent events as well, and recurring-ical-events does the same for an icalendar.Calendar object.

How do I sync a calendar from a server using icalendar?

You add the caldav package, which is a CalDAV client library, an RFC 4791 implementation built on icalendar. The base library deliberately stays free of network code, so server side synchronisation is a separate dependency.

What licence is icalendar released under?

A two-clause BSD licence. The README names it as the 2-Clause BSD License and the package metadata declares BSD-2-Clause with LICENSE.rst as the licence file, although GitHub's own classifier reports the repository as having a custom licence it cannot categorise.

Official sources

  1. collective/icalendar on GitHub
  2. Issues
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/collective-icalendar.svg)](https://hysenlabs.com/projects/collective-icalendar)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/collective-icalendar.svg)](https://hysenlabs.com/projects/collective-icalendar)

Was this useful?