ICS Expand RRULE
BetaTurn the recurring events of an .ics calendar into one event per occurrence between two dates, so a spreadsheet, a CRM or an importer that cannot read RRULE still sees every meeting. Download the result as .ics, JSON or CSV. On this page, the calendar is read in your browser and nothing is uploaded.
- Free, no sign-up
- REST + MCP
- Updated
- Reviewed by Olgun Ozoktas
At most 2000.
Each occurrence between From and To becomes its own VEVENT, with no RRULE left in the file.
The expanded calendar will appear here.
How to Expand an RRULE Calendar
-
Export the calendar as .ics
In Google Calendar, Settings > Import & export > Export. Apple Calendar: File > Export. Outlook: File > Save Calendar. -
Drop the .ics file on the page, or click to choose it
-
Set From and To
Only occurrences that touch those days are written. Keep the cap per series unless you need more than 366 occurrences of one series. -
Choose .ics to import the result into another calendar, JSON for a script, or CSV for a spreadsheet, then download
Common Use Cases
Spreadsheets
CRM and billing imports that accept single events only
Legacy calendar importers that ignore RRULE and keep only the first occurrence
Checking a rule
Audits
Why Expand Recurring Events?
The expansion follows RFC 5545 section 3.3.10 for the parts most calendars use: FREQ=DAILY, WEEKLY, MONTHLY and YEARLY; INTERVAL; COUNT and UNTIL; BYDAY, including ordinals such as 2TU for the second Tuesday and -1FR for the last Friday in monthly and yearly rules; BYMONTHDAY, where a negative day counts from the end of the month; BYMONTH; and WKST. DTSTART is always the first occurrence and counts towards COUNT, even when it falls before the window. EXDATE removes occurrences, RDATE adds them, and a component with the same UID and a RECURRENCE-ID replaces the occurrence it names with its own time and details.
The arithmetic runs on the wall-clock time the file states. A series at 09:30 Europe/Istanbul is written at 09:30 Europe/Istanbul on every date, across daylight-saving changes, which is how RFC 5545 defines a recurrence. The output keeps the TZID or the trailing Z of each value. One value is read across zones: a UNTIL, EXDATE, RDATE or RECURRENCE-ID written in UTC for a series in a named zone is read in that zone, so it matches the occurrence it names.
Each series stops at the cap you set, 366 occurrences by default and at most 2000, and the whole output stops at 20,000 events. When a series is cut, the notes say which one. Single events that touch the window are copied once, unchanged. The JSON output has the same fields as ICS to JSON, and the CSV output has the same columns as the spreadsheet layout of ICS to CSV.
How it compares
Google Calendar and Outlook keep a recurring meeting as one event with a rule, and their exports do the same, so a converter that reads the export row by row sees one meeting. Writing a script with an RRULE library works, but means installing it, reading the time zones right and handling moved and cancelled occurrences yourself. This page reads the standard format, applies the exceptions the file holds, and writes plain events in the window you choose, without a library to install.
Expansion Tips
- A monthly rule on the 29th, 30th or 31st skips the months that do not have that day, as RFC 5545 says. The notes name each series this affects.
- Each occurrence gets its own UID: the series UID plus the occurrence start. Importing the result next to the original series creates duplicates, so import it into a separate calendar.
- EXDATE removes an occurrence; a component with a RECURRENCE-ID replaces one. Both are applied before anything is written.
- Times keep their TZID, or their trailing Z. Nothing is converted between zones.
- A rule that uses BYSETPOS, BYYEARDAY, BYWEEKNO, BYHOUR, BYMINUTE, BYSECOND or an hourly or finer frequency keeps its first occurrence only, and the notes say so.