Event Model
The Event class -- creation, validation, timezone support, attendees, reminders, and categories.
Overview
The Event class represents a calendar event with full timezone support, attendee management, reminders, and category tagging. Events are created through Event.normalize() which applies defaults and coerces field values.
import { Event } from '@forcecalendar/core';
const event = new Event({
id: 'team-meeting',
title: 'Team Meeting',
start: new Date('2026-03-01T09:00:00'),
end: new Date('2026-03-01T10:00:00'),
timeZone: 'America/New_York',
});Constructor Properties
| Property | Type | Default | Description |
|---|---|---|---|
id | string | Required | Unique identifier (not auto-generated by Event; assign your own) |
title | string | Required | Non-empty event title |
start | Date | string | Required | Valid start date/time |
end | Date | Same as start | End date/time |
allDay | boolean | false | All-day event flag |
description | string | '' | Event description |
location | string | '' | Event location |
color | string | null | Primary color |
backgroundColor | string | null | Background override |
borderColor | string | null | Border override |
textColor | string | null | Text color override |
recurring | boolean | false | Whether event recurs |
recurrenceRule | string|object | null | RRULE string or parsed rule object |
recurrence | string|object | null | Alias for recurrenceRule |
timeZone | string | null | IANA timezone for start time |
endTimeZone | string | null | IANA timezone for end time (if different) |
status | string | 'confirmed' | 'confirmed', 'tentative', 'cancelled' |
visibility | string | 'public' | 'public', 'private', 'confidential' |
organizer | object | null | { email, name } |
attendees | Array | [] | Attendee objects |
reminders | Array | [] | Reminder objects |
categories | Array | [] | Category strings |
category | string | null | Shorthand for single category (added to categories) |
attachments | Array | [] | Attachment objects |
conferenceData | object | null | Video conference data |
metadata | object | {} | Custom key-value metadata |
Static Methods
Event.normalize(data)
Normalize raw event data into a complete event object with defaults applied. Ensures start and end are Date objects (defaulting end to start when omitted), trims and length-limits string fields, and applies default values. It does not generate an id -- if none is provided, id defaults to an empty string.
const normalized = Event.normalize({
title: 'Quick Event',
start: '2026-03-01T09:00:00',
});
// { id: '', title: 'Quick Event', start: Date, end: Date, ... }Event.validate(data)
Validate normalized event data. Returns void and throws an Error on failure.
const normalized = Event.normalize({
id: 'meeting', title: 'Meeting',
start: new Date(2026, 9, 5, 9), end: new Date(2026, 9, 5, 10),
});
Event.validate(normalized);IDs, titles and start dates are required. Dates must be valid, and an end cannot precede the start (equal instants are allowed). Recurring events require a rule. Attendees and metadata also have validation/size constraints. Normalization defaults invalid status/visibility to supported values; it does not generate an ID. The constructor normalizes and validates its input.
Event.fromObject(obj)
Create an Event instance from a plain object.
const event = Event.fromObject(savedEventData);Computed Properties (Getters)
| Getter | Type | Description |
|---|---|---|
duration | number | Duration in milliseconds |
durationMinutes | number | Duration in minutes |
durationHours | number | Duration in hours (decimal) |
isMultiDay | boolean | Spans midnight |
isCancelled | boolean | Status is 'cancelled' |
isTentative | boolean | Status is 'tentative' |
isConfirmed | boolean | Status is 'confirmed' |
isPrivate | boolean | Visibility is 'private' |
isPublic | boolean | Visibility is 'public' |
hasAttendees | boolean | Has at least one attendee |
hasReminders | boolean | Has at least one reminder |
isMeeting | boolean | Has attendees |
isVirtual | boolean | Has conference data |
category | string|null | Primary (first) category |
Instance Methods
isRecurring()
Returns true if the event has a recurrence rule.
occursOn(date)
Check if the event occurs on a specific date (considering timezone).
event.occursOn(new Date('2026-03-01')); // trueoverlaps(otherEvent)
Check if this event's time range overlaps with another event.
const hasConflict = eventA.overlaps(eventB);contains(datetime)
Check if a specific datetime falls within this event's time range.
clone(updates?)
Create a copy of this event, optionally with modifications.
const copy = event.clone({ title: 'Copy of Meeting' });toObject()
Serialize to a plain object (for storage or transmission).
const obj = event.toObject();
JSON.stringify(obj);equals(other)
Deep equality check against another event.
Timezone Methods
getStartInTimezone(timezone)
Get the start time converted to a specific timezone.
const tokyoStart = event.getStartInTimezone('Asia/Tokyo');getEndInTimezone(timezone)
Get the end time converted to a specific timezone.
updateTimes(start, end, timezone?)
Update start/end times, optionally specifying the source timezone.
Attendee Management
addAttendee(attendee)
event.addAttendee({
email: 'alice@example.com',
name: 'Alice',
status: 'needs-action', // 'accepted', 'declined', 'tentative', 'needs-action'
role: 'required', // 'required', 'optional', 'chair'
});removeAttendee(email)
event.removeAttendee('alice@example.com');updateAttendeeResponse(email, status)
event.updateAttendeeResponse('alice@example.com', 'accepted');getAttendee(email)
Returns the attendee object for the given email, or undefined.
hasAttendee(email)
Returns boolean.
getAttendeesByStatus(status)
const accepted = event.getAttendeesByStatus('accepted');getAttendeeCounts()
const counts = event.getAttendeeCounts();
// { total: 5, accepted: 3, declined: 1, tentative: 0, 'needs-action': 1 }Reminder Management
addReminder(reminder)
event.addReminder({
type: 'email', // 'email', 'popup', 'sms'
minutes: 15, // Minutes before event
});removeReminder(reminderId)
Remove the reminder whose id matches. Returns true if a reminder was removed.
getActiveReminders()
Returns reminders that haven't triggered yet.
getReminderTriggerTimes()
Returns an array of Date objects representing when each reminder should fire.
const times = event.getReminderTriggerTimes();
// [Date(2026-03-01T08:45:00), Date(2026-03-01T08:00:00)]Category Management
addCategory(category)
event.addCategory('important');removeCategory(category)
event.removeCategory('important');hasCategory(category)
Returns boolean.
hasAnyCategory(categories)
Returns true if the event has at least one of the given categories.
event.hasAnyCategory(['meeting', 'review']); // true if has eitherhasAllCategories(categories)
Returns true if the event has all of the given categories.
Full-field snapshots and serialization
Core 2.5.6 retains endTimeZone in clone() and toObject(), alongside supported event fields. Event.isEquivalent(a, b) compares the fields used by reconciliation, including nested host data; it is distinct from relying on object identity.
All-day normalization uses local start-of-day through the inclusive last day's 23:59:59.999. Use civil-date parsing at an external adapter boundary; see date migration.
Occurrence Events produced by EventStore carry isOccurrence, recurringEventId and occurrenceStart, with stable IDs derived from the master and occurrence instant. Event.occurrenceId(masterId, start) and Event.parseOccurrenceId(id) support that identity contract. Reconciliation resolves occurrence references back to their master rather than replacing a recurring series with one visible instance.