NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
Packagist · #5647 most downloaded on Packagist
Simple iCal parser
Last release 9 days ago
29 Sep 2026
Release timing varies
gaps range from 4 weeks to 13 months
Some releases are documented
notes for 10 of 39 stable releases
Nothing withdrawn
no release was ever pulled
13 years old
39 releases · first in 2014
…ParserOptions ) with the shape of its data, now deprecated and to be removed in 5.5 at the latest. Both use a new recurrence engine and content line p…
composer require om/icalparser:^5.0Documentation: https://ozzyczech.github.io/icalparser/
Version 5 adds a new, layered API (om\ICal) for reading and creating calendars and keeps the array based API of
version 4 (IcalParser, EventsList, Freq, Recurrence, ParserOptions) with the shape of its data, now deprecated
and to be removed in 5.5 at the latest. Both use a new recurrence engine and content line parser, which fixes many bugs;
the results of affected calendars differ from 4.x.
See UPGRADING.md. The fixes of 4.1.4 (#37, #88) are included.
ICal::parse(), ICal::parseFile(), ICal::stream() and the configurable ICal::parser() withParserMode::Strict / Permissive, ParseLimits, RecurrenceLimits and a ParseResult with structured warningsContentLine, Parameters, LineReader (streams in chunks), TokenizerComponent / Property keeping unknown and X- properties; typed facades Calendar, Event,Todo, Journal, FreeBusy, Alarm, TimezoneDefinitionDateTimeValue keeps DATE, floating, UTC and zoned times apart; floating times need an explicit timezoneValueParser for all RFC 5545 value typesRANGE=THISANDFUTURE instances, lazy occurrencesBetween()occurrences(limit)Validator with severities, Serializer with UTF-8 safe foldingENCODING=QUOTED-PRINTABLE text values are decoded (with a warning), as by IcalParserSyntaxException, InvalidValueException,InvalidRecurrenceRuleException, TimezoneResolutionException, ResourceLimitException, ValidationException)examples/IMAGE, CONFERENCE, SOURCE, LINK andCONCEPT are URIs, REFRESH-INTERVAL is a DURATION, ACKNOWLEDGED is a DATE-TIME (the Validator reports aVALUE=UID and VALUE=XML-REFERENCE of RFC 9253 (#91)color() and images() (Image) of calendars and items, Calendar::source(),Calendar::refreshInterval() and Item::conferences() (Conference); of RFC 9253: Item::links() (Link) andItem::relatedTo() (Relation with RELTYPE and GAP); of RFC 9073: Item::locations() (Location ofAlarm::uid() and Alarm::acknowledged() (#92)Calendar::create() with name, description, color, method,events, todos, journals, components and properties (backward compatible), Event::new(),Todo::new(), Journal::new(), Location::new(), Alarm::display(), audio() and email(),CalAddress::create(); values are formatted and escaped, invalid combinations are rejected, a VTIMEZONE isVTimezoneBuilder), Calendar::writeFile(); Status, Classification andTransparency enums (#108)om\RRule\Rule and om\RRule\Expander with all rule parts: BYSETPOS, BYSECOND,SECONDLY, negative BYWEEKNO and BYYEARDAY, WKST for weekly intervals, date-only UNTILRSCALE and SKIP=OMIT|BACKWARD|FORWARD for RSCALE=GREGORIAN; other calendar systems and leap monthsrecurrence.unsupported-rscale) (#90)IcalParser::__construct() accepts ParserOptions; untilInterval and shiftEventDates now work and newnow (reproducible results), maxOccurrences and strictDTEND of events and instances is derived from DURATION; all-day events without DTEND last one dayIcalParser::parseDuration() for DURATION valuesgetTodos() and getJournals(); DUE and COMPLETED are parsed as datesRDATE;VALUE=PERIOD values (represented by their start)EXDATE;VALUE=DATE removes the occurrence of that day:, ; or , (e.g. CN="Doe, John", ALTREP="http://…")om\TimezoneResolver (TZID resolution with a cache)BEGIN => VCALENDAR and 0 => null entries created by blank or invalid lines_RECURRENCE_IDS is grouped by UID: [uid][recurrence-id] => eventORGANIZER-CN, attendee parameters)END:VALARM) belong to the parent component;X- components are stored under the component nameCATEGORIES items are trimmed and escaped commas no longer split themRRULE is ignored (the event keeps DTSTART and RDATE); with strict: true it throwsInvalidArgumentExceptionEXDATE but no RRULE or RDATE get RECURRENCES as well; an empty recurrence set produces no eventDTSTART and DTEND of recurring instances are copies, changing them does not modify the parsed dataparseString() receives property rows only (not BEGIN:VCALENDAR) and counter 0 for calendarparseFile() throws RuntimeException when the file cannot be read; invalid input keeps previously parsed dataIcalParser::$timezone is reset for every calendar that is not appendedFreq is an adapter over the new engine: invalid rules throw InvalidArgumentException, maxOccurrences limitsFreq::$debug has no effect, lastOccurrence() returns false for an empty set andpreviousOccurrence() returns false when there is no earlier occurrence (4.x returned DTSTART)UNTIL are compared in UTC: definitions east of UTC whose daylight saving time endedUNTIL is kept (#110)RDATE without RRULE no longer fails with TypeError and adds no yearly occurrences (#37, also in 4.1.4)RDATE values are always part of the recurrence set (one was lost together with COUNT)RECURRENCE-ID replaces only the matching instance of the same UID, compared as an instant in any timezoneDTSTARTCOUNT reaching beyond the 3 year horizon are complete (4.x failed with TypeError)BYDAY=-2MO returnedBYHOUR combined with BYMINUTE (minutes were lost) and INTERVAL of weekly rulesFreq with a string rule no longer loops foreverUTC is Etc/UTC, Pacific Standard Time (Mexico) isAmerica/Tijuana, 40 new names); Outlook display names are kept in a separate fileCompared with 4.1.3 on the sample calendars: expanding recurring events is about 4x faster, parsing a 27 MB calendar
with 50 000 events is about 20 % faster with lower peak memory, and sorting 50 000 events is about 13x faster.
The new API parses the same 27 MB calendar in 1.1 s with value checks (0.95 s without, 226 MB), streams it in 0.5 s
with 2 MB of memory, and converts values lazily.
One column per quarter.
An event with RDATE and no RRULE no longer throws a TypeError ; its occurrences are DTSTART and the RDATE values
RDATE and no RRULE no longer throws a TypeError; its occurrences are DTSTART and the RDATE values (#37)BYMONTHDAY, BYMONTH, …) are compared as integers (#88, thanks @bensynapse)BYMONTH and BYMONTHDAY (for example every January 1st) generate only the first occurrence (#59). This is fixed by the new recurrence engine of the upcoming version 5.0 and will not be fixed in 4.x.Full changelog: v4.1.3...v4.1.4
Upgrade actions/checkout from v6 to v7 in GitHub Actions workflows
actions/checkout from v6 to v7 in GitHub Actions workflowsnette/tester dev dependency to ^2.6.1Full changelog: v4.1.2...v4.1.3
Prevent timezone leakage during recurrence parsing
.gitattributes to minimize dist size (#83)Full changelog: v4.1.1...v4.1.2
Normalize 'Z' timezone to 'UTC' for recurring events
'Z' timezone to 'UTC' for recurring events (#82)fix(IcalParser): Handle multi-segment IANA timezones like America/Argentina/Buenos_Aires and America/Indiana/Indianapolis (fixes #72 )
America/Argentina/Buenos_Aires and America/Indiana/Indianapolis (fixes #72)Full Changelog : v3.2.1...v4.0.0
Full Changelog: v3.2.1...v4.0.0
Add php8.6 to experimental test by @Rotzbua in #79
Full Changelog: v3.2.0...v3.2.1
Add PHP 8.5 to test; enable dependabot to update Github Actions by @Rotzbua in #77
Full Changelog: v3.1.1...v3.2.0
Nothing published for this version
Nothing published for this version
Update readme.md by @Rotzbua in #70
Full Changelog: v3.0.5...v3.0.6
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →