1. Go to this page and download the library: Download erenav/icalendar library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
erenav / icalendar example snippets
use Erenav\ICalendar\Component\{Calendar, Event};
use Erenav\ICalendar\Serializer\IcsSerializer;
use Erenav\ICalendar\ValueType\Duration;
$calendar = Calendar::build()
->prodId('-//Acme//Booking 1.0//EN')
->add(
Event::build()
->uid('[email protected]')
->summary('Sprint Planning')
->starts(new DateTimeImmutable('2026-07-01 10:00', new DateTimeZone('UTC')))
->lasting(Duration::hours(1))
->addAttendee('[email protected]')
)
->get();
echo (new IcsSerializer)->serialize($calendar);
use Erenav\ICalendar\Component\{Calendar, Event};
use Erenav\ICalendar\Parser\Parser;
use Erenav\ICalendar\Serializer\IcsSerializer;
use Erenav\ICalendar\ValueType\Duration;
// Build
$calendar = Calendar::build()
->prodId('-//Acme//EN')
->add(
Event::build()
->uid('[email protected]')
->summary('Lunch')
->starts(new DateTimeImmutable('2026-07-01 12:00', new DateTimeZone('UTC')))
->lasting(Duration::hours(1))
)
->get();
// Serialize
$ics = (new IcsSerializer)->serialize($calendar);
// Parse back
$parsed = Parser::lenient()->parseCalendar($ics);
echo $parsed->events()[0]->summary(); // "Lunch"
use Erenav\ICalendar\Component\{Calendar, Event};
use Erenav\ICalendar\Parameter\{Role, PartStat};
use Erenav\ICalendar\Property\{EventStatus, Transparency, Classification};
use Erenav\ICalendar\ValueType\Duration;
$event = Event::build()
->uid('[email protected]')
->timestamp(new DateTimeImmutable('now', new DateTimeZone('UTC'))) // DTSTAMP
->summary('Sprint Planning, Q3') // commas/semicolons escaped automatically
->description("Agenda:\n- demo\n- retro")
->location('Room 4')
->url('https://acme.test/meetings/42')
->starts(new DateTimeImmutable('2026-07-01 09:30', new DateTimeZone('UTC')))
->lasting(Duration::hours(1)) // or ->ends($dateTime)
->status(EventStatus::Confirmed)
->transparency(Transparency::Opaque)
->classification(Classification::Private)
->priority(5)
->categories('work', 'planning')
->color('cornflowerblue') // RFC 7986
->organizer('[email protected]', name: 'The Boss')
->addAttendee('[email protected]', role: Role::Chair, rsvp: true, name: 'Alice')
->addAttendee('[email protected]', partStat: PartStat::Accepted)
->get();
$calendar = Calendar::build()
->prodId('-//Acme//Booking 1.0//EN') // VERSION defaults to 2.0
->name('Team Calendar') // RFC 7986
->add($event) // accepts components or builders
->get();
use Erenav\ICalendar\Serializer\IcsSerializer;
$ics = (new IcsSerializer)->serialize($calendar);
// Strict mode enforces the serializer's selected
use Erenav\ICalendar\Parser\Parser;
$calendar = Parser::lenient()->parseCalendar($icsString); // returns Calendar
$component = Parser::lenient()->parse($icsString); // returns the root Component
// Strict parsing throws on malformed structure and typed-value violations instead of recovering:
$calendar = Parser::strict()->parseCalendar($icsString);
use Erenav\ICalendar\ValueType\Duration;
Duration::hours(1); // PT1H
Duration::minutes(-15); // -PT15M (negative — e.g. an alarm trigger)
Duration::weeks(2); // P2W
Duration::of(days: 1, hours: 6); // P1DT6H
Duration::parse('PT90M'); // from a string
// Interop (CarbonInterval extends DateInterval, so it works too):
Duration::fromDateInterval(new DateInterval('PT1H'));
Duration::hours(1)->toDateInterval();
$copy = Event::build();
if (($property = $source->property('UID')) !== null) {
$copy->uidProperty($property);
}
if (($property = $source->property('DTSTART')) !== null) {
$copy->startProperty($property);
}
if (($property = $source->property('RECURRENCE-ID')) !== null) {
$copy->recurrenceIdProperty($property);
}
if (($property = $source->property('SEQUENCE')) !== null) {
$copy->sequenceProperty($property);
}
if (($property = $source->property('ORGANIZER')) !== null) {
$copy->organizerProperty($property);
}
foreach ($source->properties->all('ATTENDEE') as $property) {
$copy->attendeeProperty($property);
}
$copiedEvent = $copy->get();
use Erenav\ICalendar\Component\{Event, Alarm};
use Erenav\ICalendar\Property\AlarmAction;
use Erenav\ICalendar\ValueType\Duration;
$event = Event::build()
->uid('[email protected]')
->addAlarm(
Alarm::build()
->action(AlarmAction::Display)
->description('Starts in 15 minutes')
->trigger(Duration::minutes(-15)) // relative; or pass a DateTimeInterface for absolute
)
->get();
$event->alarms()[0]->action(); // AlarmAction::Display
$event->alarms()[0]->trigger(); // Duration (or DateTimeValue)
use Erenav\ICalendar\Recurrence\{Recurrence, Weekday, WeekdayRule};
Recurrence::daily()->times(10); // FREQ=DAILY;COUNT=10
Recurrence::weekly()->every(2)->on(Weekday::Monday, Weekday::Wednesday);
Recurrence::monthly()->on(new WeekdayRule(Weekday::Friday, -1)); // last Friday of the month
Recurrence::yearly()->until(new DateTimeImmutable('2030-01-01', new DateTimeZone('UTC')));
Recurrence::parse('FREQ=WEEKLY;BYDAY=MO,WE'); // from an RRULE string
$from = new DateTimeImmutable('2026-07-01 00:00:00', new DateTimeZone('UTC'));
$to = new DateTimeImmutable('2026-08-01 00:00:00', new DateTimeZone('UTC'));
foreach ($event->occurrencesBetween($from, $to) as $occurrence) {
echo $occurrence->format('Y-m-d H:i'); // DateTimeImmutable
}
foreach ($calendar->occurrencesBetween($from, $to) as $occurrence) {
$occurrence->start; // DateTimeImmutable (may differ from the slot if moved)
$occurrence->recurrenceId; // the original slot in the series
$occurrence->event; // master, detached override, or materialized range result
$occurrence->isOverride; // true if a RECURRENCE-ID override applied
$occurrence->end; // RFC-effective end (including PERIOD/implicit duration)
}