Skip to content

Calendar data

Represent calendar dates, timed events, all-day spans, and resource lanes with explicit boundaries.

Dates and instants

A calendar date is a YYYY-MM-DD string. It has no time or timezone. A timed event's start and optional end are ISO date-times with an explicit offset (Z, -07:00, for example); the core converts them to instants. Views use the timeZone IANA identifier to place instants on local days. Do not treat an offset-free wall time as an instant.

resolveCalendarLocalDateTime(date, hour, minute, second, millisecond, timeZone) resolves a wall time only if it maps to exactly one instant. It throws for a spring-forward time that does not exist and a fall-back time that occurs twice. The caller must choose how to handle those cases. getCalendarDay also throws when the requested local date does not exist in that zone.

Event identity and interval

Each event needs a non-empty stable id and title; IDs must be unique within the supplied event list. An event may include display text, href, kind, status, participants, organizer, conflict, creator, participation, attendance, proposal, action, and editable. The API reference lists the exact shapes.

Timed events use allDay: false or omit allDay. Their end is exclusive: [start, end). If end is absent, the event is a point at start; it is not a zero-length duration that can be resized.

All-day events use allDay: true. Their date-only end is also exclusive. Omitting end means the single start date, through the next local midnight in the requested timezone. A multi-day event from October 26 through October 28 uses start: "2026-10-26" and end: "2026-10-29".

Resources and lanes

A resource has a unique non-empty id and label, with optional avatar. An event's resourceId must refer to a supplied resource; omit it for an unassigned event. schedule views group by resource and also retain an unassigned lane. Lane assignment is a display calculation: it does not reserve capacity or detect business conflicts.

Validate before rendering

validateCalendarData checks the date and timezone, supported view, required event and resource identity, duplicate IDs, resource references, selected field shapes, timestamp validity, and positive duration for non-point intervals. It returns { valid, errors }; it does not repair records. Invalid offset-free timed values, impossible dates, unsupported statuses, duplicate IDs, and non-positive explicit durations produce errors. Callers remain responsible for validating server data and application rules.

calendar-data.ts

For React view props and callback payloads, see Calendar API. For the distinction between proposals and saved events, see Calendar state.

Serialization and external data

Event dates and timestamps are strings, so serialize the event records directly. Keep all-day dates as YYYY-MM-DD; converting them through new Date(...).toISOString() changes their meaning. Timed instants can be normalized to UTC with toISOString() after parsing, but that loses the authored offset. Store an IANA zone separately in your application when you need the original scheduling zone: a numeric offset does not contain DST rules.

CalendarInterval, CalendarDay and CalendarSegment are calculated views of those records. Recompute them for the requested date/zone rather than treating cached milliseconds, lane positions or a 24-hour assumption as persisted event truth. Do not round-trip a Date object through JSON and assume it revives as a Date.

Validate network payload shape before supplying typed records; a TypeScript assertion does not validate JSON. validateCalendarData checks Calendar's contract, while the application validates permissions, recurrence expansion, supported resource policy and any additional metadata. For interval comparisons use half-open bounds: an end equal to the next start is adjacency, not overlap. Display hit targets may be larger than the semantic interval.