@neo-reckoning/ical
v0.1.0
Published
iCal (.ics) parser and generator for @neo-reckoning/core. Converts VEVENT data to DateRange[] and back.
Readme
@neo-reckoning/ical
iCal (.ics) parser and generator for @neo-reckoning/core. Converts VEVENT data to DateRange[] and back.
This package parses .ics calendar data into neo-reckoning DateRange[], preserves recurrence structure when possible, and generates valid .ics output from those ranges.
What this does
- Parse VEVENT data — convert all-day events, timed events, spans, recurrence rules, and exceptions into
DateRange[] - Generate
.icsoutput — exportDateRange[]back toVCALENDAR/VEVENTform - Preserve recurrence structure — directly map simple RRULE patterns into native neo-reckoning recurrence fields
- Expand complex rules when needed — fall back to explicit date expansion for recurrence patterns that do not fit the native model
- Work in browser and Node — built on
ical.js, which runs in both environments
Install
npm install @neo-reckoning/icalQuick start
import { detectDataWindow, generateICS, parseICS } from '@neo-reckoning/ical';
const window = {
from: new Date('2026-03-01T00:00:00'),
to: new Date('2026-03-31T00:00:00'),
};
const ranges = parseICS(icsText, window);
const detected = detectDataWindow(icsText);
const ics = generateICS(ranges, { calendarName: 'Roundtrip' });API
parseICS(icsText, window)
Parses .ics text into DateRange[] within a time window.
- Single-day, timed, and multi-day VEVENTs become native neo-reckoning ranges
- Simple RRULEs map directly to recurrence fields like
everyWeekday,everyDate, andeveryMonth - Complex RRULEs are expanded to explicit
dateswithin the requested window EXDATEvalues becomeexceptDates
generateICS(ranges, options?)
Exports DateRange[] back to .ics format.
- Writes a valid
VCALENDARwrapper - Generates
VEVENTentries for single events, spans, and supported recurrence patterns - Preserves timezones,
EXDATEvalues, and optional calendar metadata such ascalendarName
detectDataWindow(icsText)
Performs a lightweight regex scan of raw .ics text to find where the actual calendar data lives.
- Scans VEVENT
DTSTART,DTEND, andUNTILvalues - Ignores unrelated timezone blocks
- Returns a padded
{ from, to }window ornullif no event dates are present
Two-tier RRULE handling
Neo-reckoning has its own native recurrence model, but .ics RRULEs are broader. This package handles them in two tiers:
- Tier 1: direct mapping — simple RRULEs are converted into native
DateRangerecurrence fields so they stay compact and editable. - Tier 2: expansion — complex RRULEs are expanded with the
rrulelibrary into explicitdateswithin the requested parse window.
Tier 2 is used for patterns like ordinal weekdays (BYDAY=2TU), non-daily INTERVAL > 1, and other RRULE parts that do not map cleanly onto the native model.
Supported patterns
| RRULE pattern | DateRange mapping | Notes |
|---|---|---|
| FREQ=DAILY | everyWeekday: [0, 1, 2, 3, 4, 5, 6] | Daily recurrence across all weekdays |
| FREQ=WEEKLY;BYDAY=... | everyWeekday | If BYDAY is omitted, the DTSTART weekday is used |
| FREQ=MONTHLY;BYMONTHDAY=... | everyDate | If BYMONTHDAY is omitted, the DTSTART day-of-month is used |
| FREQ=YEARLY;BYMONTH=... | everyMonth | If BYMONTH is omitted, the DTSTART month is used |
| UNTIL or COUNT | fromDate, toDate, fixedBetween | Bounds the recurrence window |
| EXDATE | exceptDates | Applied to both mapped and expanded recurrences |
Patterns outside those mappings fall back to Tier 2 expansion inside the requested parse window.
Round-trip
parseICS() followed by generateICS() preserves the parsed DateRange structure for supported data. That means ranges can be imported from .ics, manipulated in neo-reckoning form, then exported back without flattening simple recurrence into one-off events.
This is a structural round-trip, not a byte-for-byte source preservation guarantee.
Browser-first design
This package uses ical.js, which works in browsers and Node. That keeps the parser and generator usable in frontend apps, React Native, workers, Node services, and MCP servers without separate platform-specific implementations.
License
MIT
