CSV to ICS field reference: how spreadsheet columns become RFC 5545 properties
What an .ics file must contain, how each spreadsheet column maps onto it, and real output from the CSV to ICS converter — VEVENT, RRULE, EXDATE, VALARM and VTIMEZONE — so you can check a file by eye.
Column → property
The mapping table
| Spreadsheet column | iCalendar property | Value type | Rule |
|---|---|---|---|
| Summary / Event Title | SUMMARY | TEXT | Commas, semicolons and backslashes escaped; newlines become \n |
| Start Date + Start Time | DTSTART;TZID=zone | DATE-TIME (local) | Wall-clock time in the named IANA zone |
| End Date + End Time | DTEND;TZID=zone | DATE-TIME (local) | Must not be before DTSTART |
| All-Day Flag | DTSTART;VALUE=DATE | DATE | DTEND is exclusive: a one-day event ends the next day |
| Time Zone (IANA) | TZID + VTIMEZONE | text | Every TZID used needs a VTIMEZONE block in the file |
| Location / Room | LOCATION | TEXT | Escaped like SUMMARY |
| Description / Notes | DESCRIPTION | TEXT | The assignee is appended as “Assigned: name” |
| Assignee / Staff / Group | CATEGORIES (split files), X-WR-CALNAME | TEXT | Used as the split key and calendar name in Pro packs |
| Recurrence Rule | RRULE | RECUR | UNTIL in UTC when DTSTART has a TZID |
| Alarm Minutes | VALARM with TRIGGER:-PT30M | DURATION | Negative duration = before the start |
| (generated) | UID, DTSTAMP | text, UTC DATE-TIME | Both required in every VEVENT |
RFC 5545 requires UID and DTSTAMP in every VEVENT and DTSTART whenever the file has no METHOD; RFC 5546 also requires DTSTART for METHOD:PUBLISH files like these. In practice Google Calendar, Outlook and Apple Calendar also expect SUMMARY and DTEND or DURATION, so the converter always writes all five.
Generated output
A complete one-event file
This is the exact free output for one roster row (Alice Chen, Day Shift, 11/02/2026 7:00 AM–3:00 PM, ER, Building B) with the time zone set to America/New_York. Note the CRLF line endings (not visible here), the escaped comma in the location and the VTIMEZONE block before the event.
BEGIN:VCALENDAR VERSION:2.0 PRODID:-//csvicsconverter.com//EN CALSCALE:GREGORIAN METHOD:PUBLISH X-WR-CALNAME:Clinic roster X-WR-TIMEZONE:America/New_York BEGIN:VTIMEZONE TZID:America/New_York BEGIN:DAYLIGHT DTSTART:20260308T020000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU TZOFFSETFROM:-0500 TZOFFSETTO:-0400 TZNAME:EDT END:DAYLIGHT BEGIN:STANDARD DTSTART:20261101T020000 RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU TZOFFSETFROM:-0400 TZOFFSETTO:-0500 TZNAME:EST END:STANDARD END:VTIMEZONE BEGIN:VEVENT UID:159564b3714589-16872c@csvicsconverter.com DTSTAMP:20261027T080000Z DTSTART;TZID=America/New_York:20261102T070000 DTEND;TZID=America/New_York:20261102T150000 SUMMARY:Day Shift LOCATION:ER\, Building B DESCRIPTION:Triage lead\; bring badge\nAssigned: Alice Chen TRANSP:OPAQUE END:VEVENT END:VCALENDAR
The header lines matter: VERSION:2.0 and PRODID are required, CALSCALE:GREGORIAN is the default made explicit, METHOD:PUBLISH tells Outlook to import rather than treat events as invitations, and X-WR-CALNAME names the calendar in Apple Calendar and Google.
Repeating events
RRULE, EXDATE and VALARM
| RRULE part | Meaning | Example |
|---|---|---|
FREQ | Repeat unit | DAILY, WEEKLY, MONTHLY |
INTERVAL | Every n units | INTERVAL=2 = every other week |
BYDAY | Weekdays in a weekly rule | MO,WE,FR |
UNTIL | Last possible date (inclusive) | 20261212T045900Z = end of 11 Dec in New York |
COUNT | Number of occurrences (instead of UNTIL) | COUNT=12 |
WKST | Week start for INTERVAL > 1 | WKST=MO |
A Monday-Wednesday-Friday class from 9 September to 11 December, skipping Columbus Day, Veterans Day and the day after Thanksgiving, with reminders 30 and 10 minutes before. This VEVENT comes from the Pro repeat pack’s writer:
BEGIN:VEVENT UID:088972e46cf08a-170e4d@csvicsconverter.com DTSTAMP:20261027T080000Z DTSTART;TZID=America/New_York:20260909T090000 DTEND;TZID=America/New_York:20260909T095000 RRULE:FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=20261212T045900Z EXDATE;TZID=America/New_York:20261012T090000,20261111T090000,20261127T09000 0 SUMMARY:BIO 101 Lecture LOCATION:SCI-204 DESCRIPTION:Assigned: Dr. Maya Patel TRANSP:OPAQUE BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:BIO 101 Lecture in 30 min TRIGGER:-PT30M END:VALARM BEGIN:VALARM ACTION:DISPLAY DESCRIPTION:BIO 101 Lecture in 10 min TRIGGER:-PT10M END:VALARM END:VEVENT
Two details trip up hand-written files. First, when DTSTART carries a TZID, RFC 5545 requires UNTIL to be written in UTC; a bare date there is ignored by some apps. Second, each EXDATE must match an occurrence exactly, including the time, or the holiday class still appears.
Time zones
VTIMEZONE blocks
A VTIMEZONE describes a zone’s offsets and when they change, so an app can place local times without its own database. Zones without daylight saving need one STANDARD block; zones with it need a DAYLIGHT and a STANDARD block, usually as yearly rules. Both examples were generated from the browser’s IANA database:
BEGIN:VTIMEZONE TZID:Asia/Tokyo BEGIN:STANDARD DTSTART:19700101T000000 TZOFFSETFROM:+0900 TZOFFSETTO:+0900 TZNAME:GMT+9 END:STANDARD END:VTIMEZONE
BEGIN:VTIMEZONE TZID:Europe/London BEGIN:DAYLIGHT DTSTART:20260329T010000 RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU TZOFFSETFROM:+0000 TZOFFSETTO:+0100 TZNAME:GMT+1 END:DAYLIGHT BEGIN:STANDARD DTSTART:20261025T020000 RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU TZOFFSETFROM:+0100 TZOFFSETTO:+0000 TZNAME:GMT END:STANDARD END:VTIMEZONE
Outlook desktop is the strictest reader: a TZID without a matching VTIMEZONE can be shifted or rejected. Google and Apple usually recognise IANA names on their own, but writing the block costs nothing and removes the risk.
Line rules
Folding, escaping and UIDs
Content lines longer than 75 octets must be folded: break the line and start the continuation with one space. Octets, not characters — an accented letter is two bytes in UTF-8 and must never be split. A long description folds like this:
DESCRIPTION:Covers the staff huddle\, overlaps the day shift\, and hands ov er to the evening charge nurse at 3 PM
| Problem in a file | Typical effect | How the converter handles it |
|---|---|---|
| Bare LF line endings | Strict parsers reject the file | Always CRLF |
| Unescaped comma in LOCATION | Text cut at the comma | Escaped as \, |
| Random UID on every export | Duplicates when re-importing | UID hashed from the row content |
| Same UID on two events | Only one survives | Identical rows get numbered UIDs |
| All-day DTEND equal to DTSTART | Zero-length or missing event | DTEND set to the next day |
| Floating times (no TZID, no Z) | Shown in each viewer’s own zone | TZID or UTC always written |
Importing into Google? The Google Calendar import guide covers the CSV route and its limits. Splitting a roster into files per person is on the schedule CSV to ICS page, and the reverse direction — reading an .ics back into a spreadsheet — is the ICS to CSV converter.