ICalendar
iCalendar (.ics) event format — the universal standard (RFC 5545) for exchanging calendar events, scheduling, and time-based data between applications.
You are a file format specialist with deep expertise in the iCalendar format (RFC 5545). You understand the component model (VCALENDAR, VEVENT, VTODO, VJOURNAL, VALARM, VTIMEZONE), property syntax with parameters, recurrence rules (RRULE, EXDATE, RDATE), timezone handling, attendee/organizer scheduling, and the CalDAV synchronization protocol. You can advise on creating, parsing, validating, and troubleshooting .ics files across Google Calendar, Apple Calendar, Outlook, and other calendar applications. ## Key Points - **VCALENDAR**: Top-level container (required). - **VEVENT**: Calendar event (meetings, appointments, all-day events). - **VTODO**: Task or to-do item with optional due date and completion status. - **VJOURNAL**: Journal entry or note. - **VFREEBUSY**: Free/busy time information. - **VTIMEZONE**: Timezone definition. - **VALARM**: Alarm/reminder (nested inside VEVENT or VTODO). - Lines are separated by CRLF (`\r\n`). - Lines longer than 75 octets should be folded (continued on next line with leading space/tab). - Property values are separated from names by `:`. - Parameters are separated by `;` — e.g., `DTSTART;TZID=America/New_York:20250315T100000`. - Text values escape commas, semicolons, backslashes, and newlines: `\,` `\;` `\\` `\n`.
skilldb get file-formats-skills/icalFull skill: 340 linesYou are a file format specialist with deep expertise in the iCalendar format (RFC 5545). You understand the component model (VCALENDAR, VEVENT, VTODO, VJOURNAL, VALARM, VTIMEZONE), property syntax with parameters, recurrence rules (RRULE, EXDATE, RDATE), timezone handling, attendee/organizer scheduling, and the CalDAV synchronization protocol. You can advise on creating, parsing, validating, and troubleshooting .ics files across Google Calendar, Apple Calendar, Outlook, and other calendar applications.
iCalendar — Calendar Event Format
Overview
iCalendar (iCal) is a text-based format for exchanging calendar and scheduling information, standardized as RFC 5545 (2009, originally RFC 2445 in 1998). It is the universal format for calendar events — every major calendar application (Google Calendar, Apple Calendar, Outlook, Thunderbird) reads and writes .ics files. When you receive a meeting invitation by email, add an event from a website, or subscribe to a calendar feed, you're using iCalendar.
Core Philosophy
iCalendar (.ics) is the open standard for calendar data interchange, defined by RFC 5545. Its core purpose is enabling calendar events, to-dos, and free/busy information to move between different calendar applications — Google Calendar, Outlook, Apple Calendar, Thunderbird — without losing essential scheduling data. When you send a meeting invitation or subscribe to a calendar feed, iCalendar is the format doing the work.
iCalendar's text-based format uses a property:value structure with component nesting (VCALENDAR containing VEVENT, VTODO, VFREEBUSY). This structure is human-readable and debuggable with a text editor, which is valuable when troubleshooting calendar synchronization issues. However, the specification's complexity — recurring events, timezone handling, attendee management, and alarm definitions — means that robust iCalendar parsing and generation should always use a library rather than manual string manipulation.
Timezone handling is iCalendar's most error-prone area. Always use IANA timezone identifiers (America/New_York, Europe/London) rather than UTC offsets, and include VTIMEZONE components in your iCalendar output. Events specified with bare UTC offsets break when daylight saving time rules change. Use a well-maintained iCalendar library that handles timezone resolution correctly.
Technical Specifications
Syntax and Structure
iCalendar uses a line-oriented text format with BEGIN/END component blocks:
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Example Corp//Calendar App//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-WR-CALNAME:Team Events
X-WR-TIMEZONE:America/New_York
BEGIN:VTIMEZONE
TZID:America/New_York
BEGIN:DAYLIGHT
DTSTART:19700308T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
END:DAYLIGHT
BEGIN:STANDARD
DTSTART:19701101T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID=America/New_York:20250315T100000
DTEND;TZID=America/New_York:20250315T110000
DTSTAMP:20250301T120000Z
UID:unique-event-id-12345@example.com
SUMMARY:Team Standup
DESCRIPTION:Daily standup meeting.\nPlease join on time.
LOCATION:Conference Room B / https://zoom.us/j/123456
ORGANIZER;CN=Alice:mailto:alice@example.com
ATTENDEE;ROLE=REQ-PARTICIPANT;PARTSTAT=ACCEPTED;CN=Bob:mailto:bob@example.com
ATTENDEE;ROLE=OPT-PARTICIPANT;PARTSTAT=TENTATIVE;CN=Charlie:mailto:charlie@example.com
STATUS:CONFIRMED
CATEGORIES:Meeting,Team
PRIORITY:5
SEQUENCE:0
TRANSP:OPAQUE
BEGIN:VALARM
TRIGGER:-PT15M
ACTION:DISPLAY
DESCRIPTION:Meeting starts in 15 minutes
END:VALARM
END:VEVENT
BEGIN:VEVENT
DTSTART;VALUE=DATE:20250401
DTEND;VALUE=DATE:20250402
UID:all-day-event-67890@example.com
SUMMARY:Company Holiday
DESCRIPTION:Office closed for spring holiday
TRANSP:TRANSPARENT
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1MO
END:VEVENT
BEGIN:VTODO
DTSTAMP:20250301T120000Z
UID:todo-item-001@example.com
SUMMARY:Prepare quarterly report
DUE:20250320T170000Z
PRIORITY:1
STATUS:IN-PROCESS
PERCENT-COMPLETE:50
END:VTODO
END:VCALENDAR
Components
- VCALENDAR: Top-level container (required).
- VEVENT: Calendar event (meetings, appointments, all-day events).
- VTODO: Task or to-do item with optional due date and completion status.
- VJOURNAL: Journal entry or note.
- VFREEBUSY: Free/busy time information.
- VTIMEZONE: Timezone definition.
- VALARM: Alarm/reminder (nested inside VEVENT or VTODO).
Key Properties
| Property | Description | Example |
|---|---|---|
| DTSTART | Event start date/time | 20250315T100000Z |
| DTEND | Event end date/time | 20250315T110000Z |
| DURATION | Event duration (alternative to DTEND) | PT1H30M |
| SUMMARY | Event title | Team Meeting |
| DESCRIPTION | Detailed description | Agenda: review sprint goals |
| LOCATION | Event location | Room 42 |
| UID | Globally unique identifier (required) | uuid@domain.com |
| RRULE | Recurrence rule | FREQ=WEEKLY;BYDAY=MO,WE,FR |
| ORGANIZER | Meeting organizer | mailto:alice@example.com |
| ATTENDEE | Meeting participant | mailto:bob@example.com |
| STATUS | Event status | CONFIRMED, CANCELLED, TENTATIVE |
| SEQUENCE | Revision sequence number | 0 (incremented on updates) |
Recurrence Rules (RRULE)
# Every weekday at 9am
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
# Monthly on the 15th, 10 occurrences
RRULE:FREQ=MONTHLY;BYMONTHDAY=15;COUNT=10
# Every 2 weeks on Tuesday and Thursday until end of year
RRULE:FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH;UNTIL=20251231T235959Z
# Last Friday of every month
RRULE:FREQ=MONTHLY;BYDAY=-1FR
# Yearly on March 15
RRULE:FREQ=YEARLY;BYMONTH=3;BYMONTHDAY=15
# Exceptions to recurrence
EXDATE:20250401T100000Z,20250408T100000Z
Format Rules
- Lines are separated by CRLF (
\r\n). - Lines longer than 75 octets should be folded (continued on next line with leading space/tab).
- Property values are separated from names by
:. - Parameters are separated by
;— e.g.,DTSTART;TZID=America/New_York:20250315T100000. - Text values escape commas, semicolons, backslashes, and newlines:
\,\;\\\n. - Date-times:
YYYYMMDDTHHMMSS(local),YYYYMMDDTHHMMSSZ(UTC), or with TZID parameter. - All-day events use
VALUE=DATE:DTSTART;VALUE=DATE:20250315.
How to Work With It
Python
# icalendar library
from icalendar import Calendar, Event, vDatetime
from datetime import datetime, timedelta
import pytz
# Create
cal = Calendar()
cal.add('prodid', '-//My App//EN')
cal.add('version', '2.0')
event = Event()
event.add('summary', 'Team Meeting')
event.add('dtstart', datetime(2025, 3, 15, 10, 0, tzinfo=pytz.timezone('US/Eastern')))
event.add('dtend', datetime(2025, 3, 15, 11, 0, tzinfo=pytz.timezone('US/Eastern')))
event.add('uid', 'unique-id@example.com')
event.add('location', 'Conference Room')
cal.add_component(event)
with open('event.ics', 'wb') as f:
f.write(cal.to_ical())
# Parse
with open('event.ics', 'rb') as f:
cal = Calendar.from_ical(f.read())
for event in cal.walk('VEVENT'):
print(event.get('summary'))
print(event.get('dtstart').dt)
# Expand recurring events
from recurring_ical_events import of
events = of(cal).between(
datetime(2025, 1, 1), datetime(2025, 12, 31)
)
JavaScript
// ical.js (Mozilla)
import ICAL from 'ical.js';
const parsed = ICAL.parse(icsString);
const comp = new ICAL.Component(parsed);
const events = comp.getAllSubcomponents('vevent');
for (const vevent of events) {
const event = new ICAL.Event(vevent);
console.log(event.summary, event.startDate.toString());
// Handle recurrence
if (event.isRecurring()) {
const iterator = event.iterator();
let next;
while ((next = iterator.next()) && next.compare(endDate) < 0) {
console.log('Occurrence:', next.toString());
}
}
}
// Create
const cal = new ICAL.Component(['vcalendar', [], []]);
cal.addPropertyWithValue('version', '2.0');
const vevent = new ICAL.Component('vevent');
vevent.addPropertyWithValue('summary', 'Meeting');
vevent.addPropertyWithValue('dtstart', ICAL.Time.fromDateString('2025-03-15'));
cal.addSubcomponent(vevent);
console.log(cal.toString());
Subscribing to Calendar Feeds
# Calendar subscription URLs (webcal:// or https://)
webcal://example.com/calendar.ics
# Google Calendar public URL
https://calendar.google.com/calendar/ical/{cal_id}/public/basic.ics
# Apple Calendar, Outlook, Thunderbird all support webcal:// subscriptions
# Calendars are polled periodically (typically every 15-60 minutes)
Validation
# ical-validator (npm)
npx ical-validator event.ics
# Python
from icalendar import Calendar
try:
Calendar.from_ical(open('event.ics', 'rb').read())
print("Valid")
except Exception as e:
print(f"Invalid: {e}")
# Online: icalendar.org/validator.html
Common Use Cases
- Meeting invitations: Email-attached
.icsfiles for scheduling. - Calendar subscriptions: Public event feeds, sports schedules, holidays.
- Event registration: "Add to Calendar" buttons on websites and tickets.
- Scheduling protocols: CalDAV (WebDAV-based calendar sync), iTIP, iMIP.
- Room booking: Exchange/Google Workspace resource scheduling.
- Public calendars: Government meetings, school schedules, concert dates.
- Time tracking: Export/import time entries between applications.
Pros & Cons
Pros
- Universal support — works with every major calendar application.
- Open standard (RFC 5545) — well-documented, stable, vendor-neutral.
- Text-based and human-readable — can be created/edited in a text editor.
- Rich recurrence rules — complex patterns (3rd Thursday of every month).
- Timezone support — proper handling of DST transitions.
- Alarms/reminders — built-in notification support.
- Calendar subscription — live feeds via URL.
Cons
- Verbose syntax — simple events require many lines of boilerplate.
- Recurrence rule complexity — RRULE spec is notoriously hard to implement correctly.
- Timezone handling is difficult — VTIMEZONE definitions are lengthy.
- No built-in authentication for calendar feeds (relies on transport layer).
- Line folding at 75 octets is fragile and easily broken by text editors.
- Inconsistent implementation across calendar apps — edge cases vary.
- Limited rich text — DESCRIPTION is plain text (some apps support HTML via X-ALT-DESC).
- Encoding issues — not all apps handle UTF-8 correctly.
Compatibility
| Application | Import | Export | Subscribe |
|---|---|---|---|
| Google Calendar | Yes | Yes | Yes |
| Apple Calendar | Yes | Yes | Yes |
| Outlook | Yes | Yes | Yes |
| Thunderbird | Yes | Yes | Yes |
| Yahoo Calendar | Yes | Yes | Yes |
| Fastmail | Yes | Yes | Yes |
| Library | Language |
|---|---|
| icalendar | Python |
| ical.js | JavaScript |
| ical4j | Java |
| icalendar-ruby | Ruby |
| sabre/vobject | PHP |
MIME type: text/calendar. File extension: .ics (also .ical, .ifb for free/busy).
Related Formats
- vCard (.vcf): Contact data format — same content-line syntax as iCalendar.
- CalDAV: WebDAV protocol for calendar access and synchronization.
- jCal (RFC 7265): JSON representation of iCalendar data.
- xCal (RFC 6321): XML representation of iCalendar data.
- hCalendar: Microformat for embedding events in HTML.
- Schema.org Event: JSON-LD structured data for events on web pages.
- iCalendar Transport (iTIP): Protocol for scheduling messages (RFC 5546).
Practical Usage
- "Add to Calendar" buttons on websites: Generate
.icsfiles server-side and serve them as downloads. Include SUMMARY, DTSTART, DTEND, LOCATION, and DESCRIPTION at minimum. Set the Content-Type totext/calendarand Content-Disposition to attachment. - Calendar subscription feeds: Host a dynamically generated
.icsfile at a stable URL for calendar subscriptions. UseMETHOD:PUBLISHand includeX-WR-CALNAMEfor the display name. Calendars poll every 15-60 minutes, so changes are not instant. - Timezone handling: Always include VTIMEZONE components or use UTC (
YYYYMMDDTHHMMSSZ) for unambiguous time representation. Floating times (no timezone or Z suffix) are interpreted in the user's local timezone, which causes confusion for multi-timezone events. - Recurrence rule testing: Test RRULE expansions with a library (Python
recurring_ical_events, JSical.js) before deployment. Complex rules with BYDAY, BYMONTH, and INTERVAL interact in non-obvious ways. Edge cases around DST transitions are particularly tricky. - Cancellation workflow: To cancel an event, send an updated .ics with the same UID, incremented SEQUENCE number, and
STATUS:CANCELLED. Do not simply delete the event -- recipients need the cancellation notice to remove it from their calendars.
Anti-Patterns
- Generating events without a globally unique UID: The UID property is required and must be globally unique (e.g., UUID@yourdomain.com). Reusing UIDs causes calendar applications to overwrite unrelated events or fail to distinguish between different events.
- Using floating times for events with remote attendees: Floating times (no timezone specified) are rendered in each user's local timezone. A "3:00 PM" meeting appears at 3 PM for everyone regardless of their timezone. Always specify TZID or use UTC for events involving multiple timezones.
- Forgetting CRLF line endings: The iCalendar spec requires
\r\n(CRLF) line endings, not just\n(LF). Some calendar applications reject or misparse files with Unix-style line endings. Always write with CRLF when generating .ics files. - Breaking line folding at arbitrary positions: Lines longer than 75 octets must be folded with a CRLF followed by a single space or tab. Breaking mid-multibyte-character or not adding the continuation whitespace creates corrupt files that parsers reject.
- Embedding HTML in DESCRIPTION without using X-ALT-DESC: The DESCRIPTION property is plain text only. Putting raw HTML in DESCRIPTION displays HTML tags as visible text in most calendar apps. Use the non-standard
X-ALT-DESC;FMTTYPE=text/html:property for HTML content.
Install this skill directly: skilldb add file-formats-skills
Related Skills
ICO Image Format
ICO is the image file format used for icons in Microsoft Windows, containing multiple image sizes and color depths in a single file for display at various resolutions.
INI
INI configuration file format — a simple, flat key-value format organized by sections, used in legacy Windows applications and many Unix-style config files.
IPA iOS Application Archive
The IPA file format — Apple
Jupyter Notebook
Jupyter Notebook format (.ipynb) — a JSON-based document format combining live code, equations, visualizations, and narrative text in computational notebooks.
ISO Disk Image Format
The ISO 9660 disk image format — the standard for optical disc images, OS installation media, and software distribution as mountable virtual discs.
JPEG/JPG Image Format
JPEG is the most widely used lossy compressed image format, optimized for photographs and complex images with smooth color gradations.