cal
Calendar and scheduling - create events with recurrence rules, export and import iCal/ICS, query events by date range or attendee, check availability, generate meeting-time suggestions, produce free/busy reports, and count business days.
Load with: use cal
What this module does
cal is a full-featured calendaring library. Build a calendar with
named events, attach recurrence rules (daily, weekly, monthly, yearly), export to
standard .ics format consumable by Google Calendar, Outlook, or Apple
Calendar, and import .ics files back into a calendar object.
Queries let you find events in a time window, events at a specific moment, or events
by attendee email. Availability checks find free slots of a required duration,
and calsg suggests the best meeting times across a search window.
Quick example
use cal
use tim
# Create a calendar
c = calne("Work")
# Add a recurring weekly meeting
now = tim.now()
ev = clvne("Team sync", now, now + 3600, {
loc: "Conference Room A",
rrule: clrrn("WEEKLY", {byday: ["MO"], cnt: 10})
})
c = caldd(c, ev)
# Export to ICS
ics = cl2cs(c)
fs.wr("work.ics", ics)
# Import from ICS
c2 = clfrm(fs.rd("other.ics"))
# Find free slots for a 1-hour meeting tomorrow
slots = clfre(c, now + 86400, 3600, 300)
prn(slots)
# Count business days
days = clbsd(now, now + 14 * 86400, nil)
Functions
Calendar
calne(name)
Creates a new calendar with a name, empty event list, default timezone from tim.tzdf(), and a standard PRODID.
caldd(calendar, event)
Appends an event to the calendar. Returns the updated calendar.
calrm(calendar, uid)
Removes an event by UID. Returns the updated calendar.
calgt(calendar, uid)
Returns the event with the given UID, or nil.
calpd(calendar, event)
Updates an existing event (matched by UID) and sets mod to now. Returns the updated calendar.
Events
clvne(summary, start, end, opts)
Creates a VEVENT. start and end are Unix timestamps.
Optional fields in opts: uid, loc, desc,
url, org, att (attendees list), cat
(categories), stat (default "CONFIRMED"), pri
(default 0), cls (default "PUBLIC"), rrule,
exdt (exclusion dates), and alarm.
calud()
Generates a unique event ID in the form "ilusm-{ms}-{rand}@ilusm".
Recurrence rules
clrrn(freq, opts)
Creates a recurrence rule. freq: "DAILY", "WEEKLY", "MONTHLY", "YEARLY". Options: int (interval, default 1), cnt (max occurrences), until (end timestamp), byday, bymth, bymd, byhour, bymin, wkst, setpos.
clxpd(rrule, start, end)
Expands a recurrence rule into a list of individual occurrence timestamps between start and end (capped at 1000). Respects exdt exclusions and cnt limits.
clnxt(rrule, dt)
Computes the next occurrence timestamp after dt. Daily adds 86400 × interval seconds; weekly adds 604800 × interval; monthly and yearly delegate to host natives __cal_add_mth and __cal_add_yr.
iCal export
cl2cs(calendar)
Serialises the calendar to a valid VCALENDAR string with CRLF line endings, ready to write to a .ics file.
clv2c(event)
Serialises a single event to a list of VEVENT lines. Includes UID, SUMMARY, DTSTART, DTEND, LOCATION, DESCRIPTION, URL, ORGANIZER, ATTENDEE, CATEGORIES, STATUS, CLASS, CREATED, LAST-MODIFIED, RRULE, EXDATE, and VALARM blocks.
clfmt(timestamp)
Formats a Unix timestamp as an iCal datetime string (YYYYMMDDTHHMMSSz).
clrr2(rrule)
Serialises a recurrence rule to an RRULE:... line.
iCal import
clfrm(ics_string)
Parses an ICS string and returns a calendar object. Parses UID, SUMMARY, DTSTART, DTEND, LOCATION, DESCRIPTION, and RRULE from VEVENT blocks.
Queries
clvbt(calendar, start, end)
Returns all events that overlap the given time range (event.start < end and event.end > start).
calvn(calendar, ts)
Returns all events that contain the given timestamp (start ≤ ts ≤ end).
clvtt(calendar, email)
Returns all events that include the given email in the attendee list.
Availability
clfre(calendar, start, duration, mingap)
Finds free time slots of at least duration seconds starting from start, with a minimum gap of mingap seconds between existing events. Returns a list of candidate start timestamps.
calsg(calendar, duration, opts)
Suggests up to opts.max meeting times (default 5) in a search window. Steps through the window in opts.step increments (default 30 min) and filters for free slots of duration.
calfb(calendar, start, end, resolution)
Returns a free/busy report listing all busy intervals in the range.
clfb2(freebusy)
Serialises a free/busy report to a VFREEBUSY ICS string.
Alarms
cllr1(action, trigger)
Creates a VALARM with the given action ("DISPLAY" or "EMAIL") and trigger.
cllr0(mins)
Creates a relative-before trigger: fires mins minutes before the event.
Attendees and RSVP
caltt(email, opts)
Creates an attendee with optional common name, role (default "REQ-PARTICIPANT"), RSVP flag, status (default "NEEDS-ACTION"), and type (default "INDIVIDUAL").
clrsv(event, email, response)
Updates an attendee's RSVP status. response is a status string like "ACCEPTED" or "DECLINED".
clnv2(event)
Generates an invitation ICS string with METHOD:REQUEST prepended - suitable for sending as a calendar invite.
Business days
clshl(timestamp, country)
Returns tru if the date is a public holiday in the given country (defaults to "US"). Delegates to host native __cal_is_holiday.
clbsd(start, end, calendars)
Counts business days between two timestamps - excludes weekends (tim.dow(d) ≥ 5) and US public holidays.
Notes
- All timestamps are Unix seconds.
- Monthly and yearly recurrence advance via host natives
__cal_add_mth/__cal_add_yrto handle month-length differences correctly. - Holiday detection requires
__cal_is_holidayin the host runtime. - Requires
trl,txt,tim, andjsn.