iCalendar
An ICS file is plain-text calendar data per RFC 5545 (IETF, 1998) — every calendar app from Google to Apple to Outlook reads it, but each interprets recurrence rules and time zones slightly differently.
ICS conversion is not yet available in FileDex. For now, use the CLI commands in the Developer Door to convert between calendar formats with python-icalendar or grep.
Common questions
How do I open an .ics file?
Double-click the file to open it in your default calendar app — Google Calendar (web), Apple Calendar (Mac/iOS), Microsoft Outlook (Windows/Mac), or Mozilla Thunderbird. ICS is plain text, so any text editor (Notepad, TextEdit, VS Code) shows the raw structure if you want to inspect it directly.
How do I add an .ics file to Google Calendar?
Open Google Calendar in your browser. Click the gear icon → Settings → Import & Export → Import. Select the .ics file and choose which calendar to add the events to. You can also drag the .ics file directly onto the Google Calendar interface. For recurring subscriptions, use 'From URL' under Other calendars.
What is the difference between ICS and CalDAV?
ICS is the file format that stores calendar events as plain text per RFC 5545. CalDAV (RFC 4791) is the HTTP-based sync protocol that calendar apps use to keep events synchronized with a server. CalDAV is not an alternative to ICS — CalDAV uses ICS as its data payload. The format is the message; the protocol is the post office.
Why does my ICS event show the wrong time after import?
ICS times can be expressed three ways: with a Z suffix (UTC, unambiguous), with a TZID parameter (local time in a named timezone), or with no timezone (floating time interpreted in the viewer's local timezone). When the source uses a TZID the destination calendar doesn't recognize, or when DST rules differ between source and destination, events shift hours.
How do I subscribe to a calendar feed instead of downloading a file?
Use a `webcal://` URL or paste an HTTPS URL ending in .ics into your calendar app's 'Add calendar by URL' option. Google Calendar: Other calendars → From URL. Apple Calendar: File → New Calendar Subscription. Outlook: Add calendar → Subscribe from web. The feed refreshes on the interval set by the server's REFRESH-INTERVAL property, so holiday calendars, sports schedules, and subscription events update automatically without re-downloading.
What makes .ICS special
Click any 'Add to Calendar' button on the web. The download is a small text file beginning BEGIN:VCALENDAR — bytes that every calendar app in the world knows how to read, and every calendar app in the world reads slightly differently. That divergence is the iCalendar story.
Continue reading — full technical deep dive
Every Calendar App Reads ICS. None Agree On What Happens Next. Why?
The iCalendar format is universal. Apple Calendar, Google Calendar, Microsoft Outlook, Mozilla Thunderbird, and every CalDAV server speak text/calendar natively. Drop a .ics file into any of them and it imports without conversion.
What is not settled is what the calendar app does next.
A VCALENDAR container holds one or more components: VEVENT for meetings, VTODO for tasks, VJOURNAL for journal entries, VFREEBUSY for availability lookups, VTIMEZONE for timezone definitions, and VALARM for reminders nested inside events. Every component is delimited by BEGIN:NAME and END:NAME markers. The required PRODID line — PRODID:-//Google Inc//Google Calendar 70.9054//EN — fingerprints the application that produced the file.
Take the same .ics file and import it into Google, Apple, and Outlook. The event arrives in all three. Reminders may arrive in two of them. Attendee status may be parsed in one. iTIP scheduling verbs (METHOD:REQUEST, METHOD:REPLY, METHOD:CANCEL per RFC 5546) are interpreted differently by each implementation. The format is universal; the behavior is local. This is the canonical iCalendar problem: every app reads ICS, none agree on edge cases. Simple events expose the gap. Recurring events widen it.
One Line Encodes a Year of Meetings. Why Is RRULE the Hardest Sentence in the Spec?
RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20271231T235959Z is one line. It also encodes a date set that calendar apps must compute correctly across decades, time zones, and exception lists.
The recurrence rule grammar gives you seven free parameters. FREQ chooses the base frequency (SECONDLY through YEARLY). INTERVAL multiplies the gap. COUNT or UNTIL bounds the series. BYDAY, BYMONTHDAY, BYMONTH, BYYEARDAY, BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND, and BYSETPOS narrow the set. Combining them produces 'every other Tuesday in months with 31 days' or 'the last weekday of each quarter' — patterns that look reasonable in English and look like dense math in RRULE syntax.
EXDATE removes specific instances. RECURRENCE-ID overrides a single instance with a different DTSTART. RDATE adds one-off occurrences that don't match the main rule.
The combinatoric expansion is why ICS parsing libraries are not small. ical.js and python-icalendar each ship thousands of lines just to expand recurrence sets correctly, and corner cases — BYDAY=FR;BYMONTHDAY=13 for Friday-the-13th, daylight-saving boundaries inside an INTERVAL=3 monthly rule, leap-day annual events on February 29 — still produce calendar bug reports decades after RFC 5545. Once the date set is computed correctly, the time zone still has to resolve — and that is where spec mechanics collide with politics.
A 9 AM Beirut Meeting Landed at Two Different UTC Moments in 2023. How?
A meeting at 9 AM in Beirut on 26 March 2023 happened at two different UTC instants depending on which faction of the Lebanese government you trusted.
ICS gives an event three ways to express a time. Add a Z suffix — DTSTART:20260415T060000Z — and the time is unambiguous UTC. Reference a TZID — DTSTART;TZID=Europe/Paris:20260415T090000 — and the time is local to that named timezone, which the parser must look up either in an embedded VTIMEZONE block or in the Olson database. Skip both and you have a 'floating time' — interpreted in whatever local timezone the viewer happens to be in.
Most cross-region scheduling complications are timezone definition disputes, not ICS spec failures. Countries that don't observe DST — Japan (UTC+09:00), India (UTC+05:30), most of Africa — are the easy case. Egypt reintroduced DST on 28 April 2023 after a decade of suspension — every Egypt-tagged ICS event from before that date may now decode wrong if the parser used a stale Olson database. Lebanon's March 2023 chaos was worse: the prime minister postponed DST to keep mornings shorter during Ramadan, Christian leaders rejected the decision, and for ~4 days Lebanon ran in two simultaneous time zones — 'Christian Time' (UTC+03:00) and 'Muslim Time' (UTC+02:00). Aviation systems, telecoms, and hospital scheduling all broke. iCalendar's flexibility — three valid ways to write a time — became the problem. Time zones are a tooling problem. Which days count as which is the deeper one.
RFC 7529 Added Non-Gregorian Recurrence in 2015. Why Does Every App Still Ignore It?
Chinese New Year moves every year by lunar calculation. Passover shifts through March and April by the Hebrew calendar. Diwali lands on a different Gregorian date each fall. Ramadan rotates backward eleven days annually through the Hijri calendar. None of these can be expressed as a simple RRULE.
ICS hardcodes the Gregorian calendar in DTSTART. RFC 7529 (2015) added the RSCALE parameter so recurring events could reference non-Gregorian calendars — Hebrew, Chinese, Islamic-Civil, Ethiopic, Indian. Ten years later, most calendar apps still ignore the parameter. Apple Calendar has basic RSCALE support. Google Calendar lacks server-side handling. Outlook, Thunderbird, and most CalDAV servers drop RSCALE silently on import.
The practical consequence: a Jewish community calendar needs a manually-maintained annual EXDATE list for Passover. A Chinese business calendar maintains two parallel subscription feeds — one for Western holidays, one for lunar ones computed offline. An Islamic prayer-time calendar publishes as a static yearly .ics file rather than a recurring rule, because no cross-app recurring rule can express 'five prayers whose times shift with sunrise' reliably.
Every non-Gregorian recurrence across every culture still comes down to Gregorian DTSTART plus externally-computed display at render time. Twenty-six years of iCalendar evolution, ten years after the spec added the fix, and the ecosystem still does not support it. The format met the technical challenge. The implementations never caught up.
.ICS compared to alternatives
| Formats | Criteria | Winner |
|---|---|---|
| .ICS vs .VCARD (VCF) | Domain ICS handles calendar/scheduling data — events, tasks, recurrence, time zones. VCF handles contact data — names, addresses, phone numbers. Both descend from the IMC's PIM-format work in the late 1990s and share line-folding, content-line, and parameter syntax. They are siblings, not competitors. | Draw |
| .ICS vs .CALDAV | File vs protocol ICS is a file format. CalDAV (RFC 4791) is an HTTP/WebDAV-based sync protocol that uses ICS as its native data payload. They are not alternatives — CalDAV requires ICS. Servers like Radicale, Baikal, and Nextcloud store every event as a .ics file inside a calendar collection. | Draw |
| .ICS vs .GOOGLE CALENDAR API | Cross-vendor portability ICS is an open IETF standard (RFC 5545) — every calendar app reads it. Google Calendar API is a proprietary REST/JSON interface useful only with Google's calendar service. Even Google Calendar exports as ICS for cross-app portability. JMAP CalendarEvent (RFC 8984) is the modern open-standard JSON alternative, but ICS still wins for vendor neutrality. | ICS wins |
Technical reference
- MIME Type
text/calendar- Developer
- IETF
- Year Introduced
- 1998
- Open Standard
- Yes — View specification
Binary Structure
ICS is plain UTF-8 text with no binary structure or magic bytes. A valid file begins with the literal text `BEGIN:VCALENDAR` (PRONOM fmt/388 signature) followed by `VERSION:2.0` and a `PRODID` identifying the producing application. Components nest via `BEGIN:NAME` / `END:NAME` markers — VEVENT for events, VTODO for tasks, VJOURNAL for notes, VTIMEZONE for timezone definitions, VALARM for reminders nested inside events. Every line terminates with CRLF; lines longer than 75 octets are folded onto the next line beginning with a single space (a legacy constraint inherited from RFC 822 email). Properties carry optional parameters via `;NAME=VALUE` between the property name and the colon (e.g., `DTSTART;TZID=Europe/Paris:20260417T123000`). Text values escape commas (`\,`), semicolons (`\;`), and newlines (`\n`).
| Offset | Length | Field | Example | Description |
|---|---|---|---|---|
Line 1 | 15 bytes | BEGIN marker | BEGIN:VCALENDAR | Required first line — also serves as content-based identification (PRONOM fmt/388 signature) |
Line 2 | 11 bytes | VERSION | VERSION:2.0 | iCalendar specification version — always 2.0 for RFC 5545 (1.0 was pre-standard vCalendar) |
Line 3 | variable | PRODID | PRODID:-//Apple Inc.//macOS 14.5//EN | Required product identifier of the application that created the file — fingerprints exporters in calendar diff tools |
Last line | 13 bytes | END marker | END:VCALENDAR | Required last line — closes the VCALENDAR container |
ICS conversion is not yet available in FileDex. For now, use the CLI commands in the Developer Door to convert between calendar formats with python-icalendar or grep.
Attack Vectors
- Mailto: ATTENDEE auto-reply data leak
- Oversized RRULE memory exhaustion
- URL-property phishing
- VTIMEZONE injection
Mitigation: Open ICS only in trusted calendar apps. Before accepting invites from unknown senders, inspect the .ics in a text editor — suspicious ATTENDEE rows and phishing URLs are visible in plain text. For server-side imports, cap RRULE expansion and disable auto-replies. Treat calendar attachments like any executable. FileDex does not parse ICS — this page is static, no upload.
- Specification RFC 5545 — Internet Calendaring and Scheduling Core Object Specification (iCalendar)
- Specification RFC 5546 — iCalendar Transport-Independent Interoperability Protocol (iTIP)
- Specification RFC 7529 — Non-Gregorian Recurrence Rules in iCalendar
- Specification RFC 4791 — Calendaring Extensions to WebDAV (CalDAV)
- Registry PRONOM fmt/388 — iCalendar
- Registry IANA text/calendar media type