Docs
/
iCalendar (.ics / RFC 5545) adapter system

ical

iCalendar (.ics / RFC 5545) format pack, pure JS with zero dependencies: build VEVENT and VCALENDAR text (createEvent, createCalendar) with summary/location/organizer/attendees/categories, parse .ics...

ical — iCalendar (.ics / RFC 5545) adapter system

Pure-JS, zero-dependency capability pack for the iCalendar file format and calendar scheduling. It builds and parses .ics text (VCALENDAR / VEVENT / VALARM), constructs and expands RFC 5545 RRULE recurrence, and derives free/busy and availability from a set of events.

Node built-ins only (node:crypto for UID generation). Deterministic: all recurrence math runs in UTC so results never drift with the host timezone. Output .ics uses CRLF line endings, 75-octet line folding, and RFC 5545 TEXT escaping.

Tools

ToolInput (one args object)Output
createEvent`{ event: { start, end\duration, summary, location, organizer, attendees, categories, allDay, rrule, alarms, uid } }` (or the fields at top level){ ics, uid, start, end, allDay, lineCount } — a VEVENT block
createCalendar{ events: [...], prodId?, name?, method?, timeZone? }{ ics, eventCount, uids, bytes } — a full VCALENDAR
parse{ ics }{ calendar, events[], eventCount } — events with ISO + epoch dates
rrule{ options: { freq, interval, count, until, byDay, byMonthDay, byMonth, byHour, byMinute, bySetPos, weekStart } }{ rrule, line, parts, summary }
expandRecurrence{ rrule, dtStart, rangeStart?, rangeEnd?, limit? }{ occurrences[], count, truncated }
freeBusy{ events: [...], rangeStart?, rangeEnd? }{ busy[], blockCount, totalBusyMs } (merged busy blocks)
availability`{ rangeStart, rangeEnd, events?\busy?, workingHours?, slotMinutes?, minMinutes? }`{ slots[], slotCount, totalFreeMs } (open/bookable slots)
addAlarm`{ ics?, alarm: { action, trigger\minutesBefore, description } }`{ ics } with a VALARM injected (or a standalone valarm)
toDataUri{ ics, filename? }{ dataUri, filename, bytes }data:text/calendar;…;base64,…
duration{ iso } or { ms }{ iso, ms } — ISO 8601 ⇄ milliseconds
validate{ ics }{ valid, errors[], warnings[], eventCount }

Dates accept ISO strings, epoch ms, or ICS date strings (YYYYMMDD, YYYYMMDDTHHMMSS, YYYYMMDDTHHMMSSZ) interchangeably. Durations use ISO 8601 (PT1H30M, P1D).

Usage

import ical from './index.js';

// 1. A weekly stand-up, every Mon/Wed/Fri at 09:00, 12 times
const rr = ical.adapters.rrule({ options: { freq: 'WEEKLY', byDay: ['MO', 'WE', 'FR'], count: 12 } });
// rr.rrule === "FREQ=WEEKLY;COUNT=12;BYDAY=MO,WE,FR"

const dates = ical.adapters.expandRecurrence({
  rrule: rr.rrule,
  dtStart: '2026-01-05T09:00:00Z',
  rangeEnd: '2026-03-01T00:00:00Z',
});
// dates.occurrences → [{ iso, ms, ics }, ...]

// 2. Build a downloadable calendar file
const cal = ical.adapters.createCalendar({
  name: 'Team',
  events: [
    { start: '2026-01-05T09:00:00Z', duration: 'PT30M', summary: 'Stand-up', rrule: rr.rrule,
      alarms: [{ action: 'DISPLAY', minutesBefore: 10 }] },
    { start: '2026-01-06', allDay: true, summary: 'Company holiday' },
  ],
});
const link = ical.adapters.toDataUri({ ics: cal.ics, filename: 'team.ics' });

// 3. Find bookable 30-min slots inside Mon–Fri 9–5, avoiding existing meetings
const slots = ical.adapters.availability({
  rangeStart: '2026-01-05T00:00:00Z',
  rangeEnd:   '2026-01-06T00:00:00Z',
  events: [{ start: '2026-01-05T10:00:00Z', end: '2026-01-05T11:00:00Z', summary: 'Sync' }],
  workingHours: { startHour: 9, endHour: 17, days: ['MO','TU','WE','TH','FR'] },
  slotMinutes: 30,
});

// 4. Round-trip: parse an .ics back to structured events
const parsed = ical.adapters.parse({ ics: cal.ics });

DRY boundary (respected — do not cross)

This pack owns exactly one thing: the iCalendar (.ics) format + its RRULE recurrence + free/busy/availability. It deliberately does not overlap its neighbours:

  • calendar renders a single date across 24 world calendar systems (Gregorian, Hebrew, Islamic

Hijri, Maya Long Count, …). That is calendar-system conversion, not file authoring. ical never converts calendar systems.

  • cron parses human intervals ('5m', '2h') and fires schedule actions (ping/print/call).

That is job scheduling. ical produces RFC 5545 RRULE recurrence for calendar events, not cron specs — and never executes actions.

  • datetime does date math (durations between dates, business-day counting, timezone

wall-clock, locale formatting, leap-year predicates). ical calls no date library and only does the minimal UTC arithmetic needed to enumerate recurrence occurrences and build slots.

If you need world-calendar conversion, interval-firing, or general date math, use those packs and pass their results in.

Source shared/engines/adapters/domain/ical/README.md (no-git)markdownjson
Generated from the Leumas repository. Every page cites the file it came from.leumas.techllms.txt