calendar / icsfile
This simple class generate a .ics file.
Requires
- php: >=8.4
Requires (Dev)
- friendsofphp/php-cs-fixer: ^v3.85
- infection/infection: ^0.32
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^12.1
- rector/rector: ^2.1
- dev-master
- 10.1.0
- 10.0.2
- 10.0.1
- 10.0.0
- 9.7.1
- 9.7.0
- 9.6.0
- 9.5.0
- 9.4.0
- 9.3.0
- 9.2.3
- 9.2.2
- 9.2.1
- 9.2.0
- 9.1.0
- 9.0.0
- 8.0.0
- 7.1.0
- 7.0.0
- 6.3.2
- 6.3.1
- 6.3.0
- 6.2.0
- 6.1.2
- 6.1.1
- 6.1.0
- 6.0.3
- 6.0.2
- 6.0.1
- 6.0.0
- 5.4.2
- 5.4.1
- 5.4.0
- 5.3.0
- 5.2.0
- 5.1.4
- 5.1.3
- 5.1.2
- 5.1.1
- 5.1.0
- 5.0.0
- 4.0.1
- 4.0.0
- 3.2.3
- 3.2.2
- 3.2.1
- 3.2.0
- 3.1.3
- 3.1.2
- 3.1.1
- 3.1.0
- 3.0.0
- 2.3.0
- 2.2.5
- 2.2.4
- 2.2.3
- 2.2.2
- 2.2.1
- 2.2.0
- 2.1.5
- 2.1.4
- 2.1.3
- 2.1.2
- 2.1.1
- 2.1.0
- 2.0.0
- 1.1.1
- 1.1.0
- dev-feature/code-use-ddd
- dev-Luc-Sanchez/add-rector-dev-dependancy-1759416547629
This package is auto-updated.
Last update: 2026-05-07 09:21:47 UTC
README
This library allows you to easily generate iCalendar (.ics) files in PHP, following the iCalendar (RFC 5545) specification.
Installation
Make sure you have installed the dependencies via Composer:
composer install
Include the Composer autoloader in your script:
require_once 'vendor/autoload.php';
Usage
Below is a basic example of creating an iCalendar event:
<?php
require_once 'vendor/autoload.php';
use Ical\Ical;
use Ical\Enum\CalendarTypeEnum;
use Ical\Enum\StatusEnum;
use Ical\Enum\TransparencyEnum;
use Ical\Exceptions\IcalendarException;
try {
$ical = (new Ical())
->setName('test')
->setAddress('Paris')
->setDateStart(new \DateTimeImmutable('2014-11-21 15:00:00', new \DateTimeZone('UTC')))
->setDateEnd(new \DateTimeImmutable('2014-11-21 16:00:00', new \DateTimeZone('UTC')))
->setDateStamp(new \DateTimeImmutable('2014-11-21 15:00:00', new \DateTimeZone('UTC')))
->setCalendarType(CalendarTypeEnum::GREGORIAN)
->setTransparency(TransparencyEnum::OPAQUE) // Optional
->setDescription('wonder description')
->setSummary('Running')
->setOrganizer('foo@bar.fr', 'Foo Bar') // Optional — second parameter sets CN (display name)
->setFilename('myFileName')
->setStatus(StatusEnum::CONFIRMED) // Optional
->setSequence(2); // Number of updates (default is 1, optional)
$ical->addHeader();
echo $ical->getICAL();
} catch (IcalendarException $exc) {
echo $exc->getMessage();
}
Methods (overview)
setName(string $name)setProdId(string $organisation, string $product, string $language = 'EN')setAddress(string $address)setDateStart(DateTimeInterface $date, bool $normalizeToUTC = true)setDateEnd(DateTimeInterface $date, bool $normalizeToUTC = true)setDateStamp(DateTimeInterface $date, bool $normalizeToUTC = true)setCalendarType(?CalendarTypeEnum $type)setTransparency(?TransparencyEnum $transparency)setDescription(string $description)setSummary(string $summary)setOrganizer(string $email, ?string $name = null)setFilename(string $filename)setStatus(StatusEnum $status)setSequence(int $sequence)setTimezoneICal(string $timezone)setAlarm(bool $enabled)setRepeat(bool $enabled)setAlarmMinutesBefore(int $minutes)setAlarmRepeat(int $repeatCount, ?int $intervalMinutes = null)setIncludeVtimezone(bool $include)setVtimezoneTzid(string $tzid)setVtimezoneStandardTzname(string $value)setVtimezoneStandardTzoffsetfrom(string $value)setVtimezoneStandardTzoffsetto(string $value)setVtimezoneStandardRrule(string $value)setVtimezoneStandardDtstart(string $value)setVtimezoneDaylightTzname(string $value)setVtimezoneDaylightTzoffsetfrom(string $value)setVtimezoneDaylightTzoffsetto(string $value)setVtimezoneDaylightRrule(string $value)setVtimezoneDaylightDtstart(string $value)addHeader()getICAL(?string $uid = null): string
PRODID (calendar identifier)
The PRODID field identifies the application that generated the file. The iCalendar standard (RFC 5545) requires the format:
-//Organisation//Product//LANG
Use setProdId() to generate a compliant PRODID. If you do not call it, the name field is used as a fallback (backward-compatible behavior).
$ical->setProdId('Bob Morane', 'Conference Calendar', 'FR');
// → PRODID:-//Bob Morane//Conference Calendar//FR
$ical->setProdId('My Company', 'Booking App');
// → PRODID:-//My Company//Booking App//EN (defaults to EN)
ORGANIZER (event organizer)
The ORGANIZER field accepts an optional CN (Common Name) parameter to display a human-readable name. Some clients such as Google Calendar require it to accept event updates.
// With display name (recommended)
$ical->setOrganizer('ariane@example.com', 'Ariane');
// → ORGANIZER;CN=Ariane:mailto:ariane@example.com
// Without name (backward-compatible)
$ical->setOrganizer('ariane@example.com');
// → ORGANIZER:mailto:ariane@example.com
Timezone handling (strict by default)
By default, this library normalizes all provided timestamps to UTC (strict mode) and emits them with a trailing Z. This ensures consistent behavior regardless of the host/server timezone.
- Strict default (real UTC normalization):
setDateStart($date)— the provided$dateis converted to UTC using its own timezone before formatting.
- Opt-out: preserve the literal clock time (no UTC conversion):
- Pass
normalizeToUTC: falseto emit the time as-is without conversion.
- Pass
Examples:
$paris = new \DateTimeImmutable('2025-10-02 10:00:00', new \DateTimeZone('Europe/Paris'));
// 1) Strict (default): convert to real UTC (10:00 Paris -> 08:00Z depending on DST)
$ical->setDateStart($paris); // outputs DTSTART:20251002T080000Z
// 2) Opt-out: keep the provided clock time as-is (no timezone conversion)
$ical->setDateStart($paris, normalizeToUTC: false); // outputs DTSTART:20251002T100000Z
Tip: For fully deterministic tests, build your DateTime with an explicit timezone (e.g., new DateTimeZone('UTC')).
Alarms (VALARM)
Two usage styles are supported and backward compatible:
- Backward-compatible flags:
setAlarm(true)enables a default reminder of 15 minutes before the event.setRepeat(true)adds a simpleREPEAT:1.
- Fine-grained configuration:
setAlarmMinutesBefore(int $minutes)sets the trigger offset before the event start, and auto-enables the alarm.setAlarmRepeat(int $repeatCount, ?int $intervalMinutes = null)setsREPEATand, if an interval is provided, adds aDURATIONline accordingly.
Examples:
// Simple: 15 minutes before, one repeat
$ical->setAlarm(true)->setRepeat(true);
// Custom: 30 minutes before, repeat 3 times every 10 minutes
$ical->setAlarmMinutesBefore(30)->setAlarmRepeat(3, 10);
VTIMEZONE
A VTIMEZONE block is included in the generated ICS only when all of the following conditions are met:
setIncludeVtimezone(true)(default) — VTIMEZONE is not disabled.setVtimezoneTzid()is called with a non-empty value that matches the value set viasetTimezoneICal().- Both
setVtimezoneStandardDtstart()andsetVtimezoneDaylightDtstart()are provided.
If any condition is not met, no VTIMEZONE block is emitted. You can also explicitly disable it regardless of the other settings:
$ical->setIncludeVtimezone(false);
Full example with VTIMEZONE for Europe/Paris:
$ical = (new Ical())
->setTimezoneICal('Europe/Paris')
->setVtimezoneTzid('Europe/Paris')
->setVtimezoneStandardTzname('CET')
->setVtimezoneStandardTzoffsetfrom('+0200')
->setVtimezoneStandardTzoffsetto('+0100')
->setVtimezoneStandardDtstart('19701025T030000')
->setVtimezoneStandardRrule('FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10')
->setVtimezoneDaylightTzname('CEST')
->setVtimezoneDaylightTzoffsetfrom('+0100')
->setVtimezoneDaylightTzoffsetto('+0200')
->setVtimezoneDaylightDtstart('19700329T020000')
->setVtimezoneDaylightRrule('FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3');
Example Output
BEGIN:VCALENDAR
PRODID:-//Bob Morane//Conference Calendar//FR
VERSION:2.0
CALSCALE:GREGORIAN
BEGIN:VEVENT
UID:myUid@foo.bar.fr
DTSTAMP:20141121T150000Z
DTSTART:20141121T150000Z
DTEND:20141121T160000Z
SUMMARY:Running
ORGANIZER;CN=Foo Bar:mailto:foo@bar.fr
LOCATION:Paris
DESCRIPTION:wonder description
STATUS:CONFIRMED
TRANSP:OPAQUE
SEQUENCE:2
END:VEVENT
END:VCALENDAR
Status values (StatusEnum)
The setStatus() method accepts a StatusEnum case:
StatusEnum::CONFIRMEDStatusEnum::TENTATIVEStatusEnum::CANCELLED
use Ical\Enum\StatusEnum;
$ical->setStatus(StatusEnum::CONFIRMED);
Error Handling
All exceptions are instances of IcalendarException.
Use try/catch to handle errors when generating the calendar.