Summary
Audit the existing ical.compat compatibility layer, document what real-world broken ICS patterns are and are not handled, and expand test coverage with real-world broken calendar file examples.
What We Already Handle
The ical.compat module has a well-designed, PRODID-aware compatibility layer that auto-detects the calendar producer and enables targeted fixups:
Microsoft Exchange Server (PRODID contains "Microsoft Exchange Server")
- Invalid timezones (
enable_allow_invalid_timezones) — tolerates TZID references that don't match any VTIMEZONE definition
- Extended timezone names (
enable_extended_timezones) — handles non-IANA timezone identifiers like "Eastern Standard Time" that Windows/Exchange uses instead of "America/New_York"
Google Calendar (PRODID contains "Google Inc//Google Calendar")
- DTSTART/UNTIL type mismatch (
enable_dtstart_until_compat) — Google Calendar generates RRULE UNTIL as a DATE when DTSTART is DATE-TIME, violating RFC 5545 section 3.3.10. The compat layer silently converts UNTIL to match DTSTART's type.
All Producers (always enabled in compat mode)
- Same-day DTEND (
enable_same_day_dtend_compat) — some providers set DTSTART and DTEND to the same date for all-day events; RFC 5545 requires DTEND to be the next day (non-inclusive)
- Invalid date formats (
enable_allow_invalid_dates) — tolerates DATE properties with time suffixes (e.g., 20240115T000000 where 20240115 is expected)
Design Pattern
The compat layer uses a context manager pattern (enable_compat_mode()) with contextvars for thread-safe state. This is an opt-in API — callers must explicitly wrap their parsing calls. This is a deliberate design choice that keeps the default parsing strict/correct.
What Developers Complain About (Real-World Broken ICS Patterns)
Based on research of Stack Overflow, GitHub issues across iCal libraries, Reddit threads, and tools like ics-fixer and x-wr-timezone:
High Frequency — Most Commonly Reported
X-WR-TIMEZONE without VTIMEZONE blocks — Google Calendar exports sometimes include only a calendar-level X-WR-TIMEZONE header and omit per-event VTIMEZONE definitions entirely. The separate x-wr-timezone library exists solely to normalize this. Status in ical: ❓ Not handled — this is likely the biggest remaining gap.
- Missing
VTIMEZONE with valid IANA TZID — Many generators include TZID=America/New_York but skip the VTIMEZONE block, assuming the client knows standard IANA zones. Technically a spec violation, but trivially resolvable since we have the tzdata package. Status: ❓ Partially handled via Exchange compat, but should work for all producers.
Moderate Frequency
- Improper line folding — RFC 5545 requires lines >75 octets to be folded (newline + space). Many generators produce long unfoldedlines, especially in DESCRIPTION and LOCATION fields. Status: ❓ Needs investigation — pyparsing grammar may already handle this.
- Missing
UID on events — Some generators omit the UID property entirely. This causes issues for recurrence and deduplication. Status: ❓ Needs investigation.
- Smart quotes and encoding issues — Descriptions copy-pasted from Word/rich-text contain smart quotes (U+201C/U+201D), em-dashes (U+2014), etc. These may cause issues if not properly UTF-8 encoded. Status: ❓ Needs investigation.
Lower Frequency
- Malformed
ORGANIZER/ATTENDEE — Empty values, missing mailto: prefix, bare email addresses. Common from Exchange and older GroupWise systems. Status: ❓ Needs investigation.
DURATION vs DTEND conflicts — Both specified on the same event, which is explicitly forbidden by RFC 5545. Status: ❓ Needs investigation.
Proposed Actions
1. Investigate and document current behavior
For each pattern above, create a test .ics file that exercises the broken pattern and document whether ical handles it (with and without compat mode).
2. Expand test coverage
Add test cases in tests/compat/ with real-world broken ICS samples. Each test should:
- Parse the broken ICS without compat mode and verify it either fails gracefully or succeeds
- Parse the broken ICS with
enable_compat_mode() and verify it produces correct results
- Document which calendar producer generates this pattern
3. Priority fixes
Based on frequency, the highest-value fixes are:
X-WR-TIMEZONE handling (covers a huge class of Google Calendar exports)
- Missing
VTIMEZONE with valid IANA TZID for all producers (not just Exchange)
- Long line handling (if not already supported)
4. Documentation
The compat layer is a genuinely great feature that's currently invisible. Document it prominently:
- Add a "Handling broken ICS files" section to the docs
- Show the
enable_compat_mode() context manager pattern in the README or quickstart
Contributions Welcome
If you encounter a broken ICS file that ical doesn't handle, please open an issue with:
- The (sanitized) ICS content
- What calendar application produced it
- What you expected to happen vs. what actually happened
Summary
Audit the existing
ical.compatcompatibility layer, document what real-world broken ICS patterns are and are not handled, and expand test coverage with real-world broken calendar file examples.What We Already Handle
The
ical.compatmodule has a well-designed, PRODID-aware compatibility layer that auto-detects the calendar producer and enables targeted fixups:Microsoft Exchange Server (
PRODIDcontains"Microsoft Exchange Server")enable_allow_invalid_timezones) — tolerates TZID references that don't match any VTIMEZONE definitionenable_extended_timezones) — handles non-IANA timezone identifiers like"Eastern Standard Time"that Windows/Exchange uses instead of"America/New_York"Google Calendar (
PRODIDcontains"Google Inc//Google Calendar")enable_dtstart_until_compat) — Google Calendar generatesRRULE UNTILas a DATE whenDTSTARTis DATE-TIME, violating RFC 5545 section 3.3.10. The compat layer silently converts UNTIL to match DTSTART's type.All Producers (always enabled in compat mode)
enable_same_day_dtend_compat) — some providers set DTSTART and DTEND to the same date for all-day events; RFC 5545 requires DTEND to be the next day (non-inclusive)enable_allow_invalid_dates) — tolerates DATE properties with time suffixes (e.g.,20240115T000000where20240115is expected)Design Pattern
The compat layer uses a context manager pattern (
enable_compat_mode()) withcontextvarsfor thread-safe state. This is an opt-in API — callers must explicitly wrap their parsing calls. This is a deliberate design choice that keeps the default parsing strict/correct.What Developers Complain About (Real-World Broken ICS Patterns)
Based on research of Stack Overflow, GitHub issues across iCal libraries, Reddit threads, and tools like
ics-fixerandx-wr-timezone:High Frequency — Most Commonly Reported
X-WR-TIMEZONEwithoutVTIMEZONEblocks — Google Calendar exports sometimes include only a calendar-levelX-WR-TIMEZONEheader and omit per-eventVTIMEZONEdefinitions entirely. The separatex-wr-timezonelibrary exists solely to normalize this. Status inical: ❓ Not handled — this is likely the biggest remaining gap.VTIMEZONEwith valid IANATZID— Many generators includeTZID=America/New_Yorkbut skip theVTIMEZONEblock, assuming the client knows standard IANA zones. Technically a spec violation, but trivially resolvable since we have thetzdatapackage. Status: ❓ Partially handled via Exchange compat, but should work for all producers.Moderate Frequency
UIDon events — Some generators omit the UID property entirely. This causes issues for recurrence and deduplication. Status: ❓ Needs investigation.Lower Frequency
ORGANIZER/ATTENDEE— Empty values, missingmailto:prefix, bare email addresses. Common from Exchange and older GroupWise systems. Status: ❓ Needs investigation.DURATIONvsDTENDconflicts — Both specified on the same event, which is explicitly forbidden by RFC 5545. Status: ❓ Needs investigation.Proposed Actions
1. Investigate and document current behavior
For each pattern above, create a test
.icsfile that exercises the broken pattern and document whethericalhandles it (with and without compat mode).2. Expand test coverage
Add test cases in
tests/compat/with real-world broken ICS samples. Each test should:enable_compat_mode()and verify it produces correct results3. Priority fixes
Based on frequency, the highest-value fixes are:
X-WR-TIMEZONEhandling (covers a huge class of Google Calendar exports)VTIMEZONEwith valid IANATZIDfor all producers (not just Exchange)4. Documentation
The compat layer is a genuinely great feature that's currently invisible. Document it prominently:
enable_compat_mode()context manager pattern in the README or quickstartContributions Welcome
If you encounter a broken ICS file that
icaldoesn't handle, please open an issue with: