Calendar / Scheduling / Recurrence DSLs Family Index
type: language-family-index family: calendar-scheduling languages_catalogued: 25 tags: [language-reference, family-index, calendar-scheduling, icalendar, vcard, rrule, cron, tzdata, jscalendar, jscontact, caldav, carddav, jmap]
Calendar / Scheduling / Recurrence — Family Index
Family overview
Calendar and scheduling DSLs are among the most-deployed structured data formats on the planet, and almost no end user knows their names. Every meeting invitation in Outlook/Gmail/Apple Calendar is iCalendar bytes (RFC 5545, originally RFC 2445 in 1998); every contact card import/export is vCard (RFC 6350, originally RFC 2426 in 1996); every CI/CD job, Linux backup, Kubernetes scheduled task, and AWS Lambda timer is some flavor of cron. The combination of multi-decade stability, embedded sub-DSLs (RRULE, EXRULE, DTSTART/DTEND, TZID), and overlapping vendor extensions makes this one of the richest and most under-studied family of formats in the wider language landscape.
The defining tension across this family is interchange-format vs. server-side scheduling. iCalendar/vCard/JSCalendar/JSContact describe content — events, todos, journals, contacts — and propagate it across mail, sync, and synchronization protocols ( JMAP). The cron family describes recurring action — “run this command every 15 minutes” — without any concept of an event object or attendee. The two traditions occasionally meet (RRULE expresses “every weekday at 09:00”, which is roughly cron’s 0 9 * * 1-5), but they evolved in distinct ecosystems: IETF/CalConnect (calendar interchange) versus Unix V7 → systemd → Kubernetes (server scheduling). Inside the iCalendar world, RRULE is the embedded recurrence sub-DSL — about 30 keywords, 20+ properties, capable of expressing “the third Thursday of each month except December” in a single line.
The 2021–2024 window saw an overdue JSON modernization: JSCalendar (RFC 8984, July 2021) and JSContact (RFC 9553, May 2024) replace the line-folded BEGIN:/END: text format with idiomatic JSON, while preserving full semantic mapping back to iCalendar/vCard. JSCalendar 2.0 is in IETF draft (calext-jscalendarbis-15, intended publication 2026), and JMAP for Calendars (draft-ietf-jmap-calendars-26, expiring May 2026) is the JSON-RPC sync protocol replacing CalDAV. Adoption is slow because the ubiquity of iCalendar/CalDAV is itself the moat — Fastmail and Apple have led, but Google and Microsoft remain on the legacy stack.
Underneath everything sits the IANA Time Zone Database (tzdata, “Olson DB”), itself a small structured language describing every legislative time-zone rule on Earth via Rule/Zone lines. The current release as of writing is 2026b (April 22, 2026), following 2026a (March 2026, Moldova DST correction). Releases happen roughly 5–10 times per year, every time a government changes a DST boundary or renames a zone. POSIX TZ strings (EST5EDT,M3.2.0,M11.1.0) are the minimal embedded subset. Together, tzdata + POSIX TZ are the substrate every other format in this family relies on for correctness.
In our deep library
None catalogued at Tier 1/2 level — calendar/scheduling DSLs do not have standalone deep-library notes; they sit on top of host languages (C, Java, Python, JavaScript) that are catalogued separately.
Cross-reference:
- api-description — CalDAV (RFC 4791) and CardDAV (RFC 6352) are WebDAV/HTTP API descriptions; JMAP is a JSON-RPC API; Google Calendar API and Microsoft Graph calendar are OpenAPI-described REST APIs.
- notation-spec — RRULE, POSIX TZ strings, cron expressions, and IANA tzdata
Rule/Zonesyntax are all formal grammars that warrant cross-link to grammar/notation indexing. - build-devops — cron is the recurring-task layer in CI/CD (GitHub Actions, GitLab CI, Jenkins, Argo Workflows) and orchestration (Kubernetes CronJob, AWS EventBridge, systemd timers).
- i18n-locale (if present) — CLDR carries calendar-system data (Hebrew, Islamic, Japanese, Buddhist, Persian, Coptic, Ethiopic) that is closely related but distinct from tzdata; CLDR concerns how to display a date, tzdata concerns which moment in UTC a wall-clock time refers to.
- citation-formats — adjacent in spirit (long-lived structured-data formats with multiple competing modernizations).
Tier 3 family table — Calendar/contact data formats
| Format | First appeared | Origin | Type | Status (2026) | URL |
|---|---|---|---|---|---|
| iCalendar (RFC 5545) | 1998 (RFC 2445) → 2009 (RFC 5545) | IETF CALSIFY WG; Internet Mail Consortium → IETF | Line-folded BEGIN:/END: text format; the universal calendar interchange | Very active — ubiquitous in every meeting invitation worldwide; minor errata accumulating | https://datatracker.ietf.org/doc/html/rfc5545 |
| vCard 4.0 (RFC 6350) | 1995 (Versit) → 1998 RFC 2426 → 2011 RFC 6350 | Versit Consortium → IETF | Line-folded contact-card format | Active — RFC 6350 (Aug 2011) remains current; extended by RFC 9554 (vCard for JSContact, 2024) | https://datatracker.ietf.org/doc/html/rfc6350 |
| jCard (RFC 7095) | 2014 | IETF | JSON representation of vCard data | Active but partially superseded by JSContact (RFC 9553) | https://datatracker.ietf.org/doc/html/rfc7095 |
| xCard (RFC 6351) | 2011 | IETF | XML representation of vCard data | Active, niche | https://datatracker.ietf.org/doc/html/rfc6351 |
| JSCalendar (RFC 8984) | July 2021 | IETF CALEXT WG (Robert Stepanek, Neil Jenkins) | JSON-native calendar data model; alternative/successor to iCalendar | Active; JSCalendar 2.0 in draft (calext-jscalendarbis, intended 2026 pub) | https://datatracker.ietf.org/doc/html/rfc8984 |
| JSContact (RFC 9553) | May 2024 | IETF CALEXT WG | JSON-native contact data model; alternative/successor to vCard | Active; companion RFC 9554 maps vCard ↔ JSContact | https://datatracker.ietf.org/doc/html/rfc9553 |
| VEVENT / VTODO / VJOURNAL | 1998 (RFC 2445) | iCalendar sub-components | Event, task, and journal-entry sub-formats inside iCalendar | Active, all three universally implemented | https://datatracker.ietf.org/doc/html/rfc5545#section-3.6 |
| VAVAILABILITY (RFC 7953) | August 2016 | IETF | Calendar-availability component for free-busy publication | Active but niche; CalDAV scheduling extension | https://datatracker.ietf.org/doc/html/rfc7953 |
| VFREEBUSY | 1998 (RFC 2445) | IETF | Busy-time exchange component within iCalendar/iTIP | Active, core to scheduling workflows | https://datatracker.ietf.org/doc/html/rfc5545#section-3.6.4 |
| VTIMEZONE / TZID | 1998 (RFC 2445) | IETF | Time-zone embedding within iCalendar; references IANA TZID strings | Active, the standard way calendars carry tz data | https://datatracker.ietf.org/doc/html/rfc5545#section-3.6.5 |
Tier 3 family table — Recurrence / scheduling DSLs
| Format | First appeared | Origin | Type | Status (2026) | URL |
|---|---|---|---|---|---|
| RRULE (iCalendar recurrence) | 1998 (RFC 2445) → 2009 (RFC 5545 §3.3.10) | IETF | Embedded recurrence DSL: FREQ=WEEKLY;BYDAY=MO,WE,FR;UNTIL=... | Active, the de facto recurrence language; ~30 keywords, 20+ properties | https://datatracker.ietf.org/doc/html/rfc5545#section-3.3.10 |
| EXDATE / EXRULE | 1998 (RFC 2445) | IETF | Recurrence exception dates / rules within iCalendar (EXRULE deprecated in RFC 5545 in favour of EXDATE) | Active (EXDATE); deprecated (EXRULE, removed from RFC 5545) | https://datatracker.ietf.org/doc/html/rfc5545#section-3.8.5.1 |
| Unix cron (5-field) | 1975 (V7 Unix, Brian Kernighan) | AT&T Bell Labs / Vixie cron (1987 onwards) | 5-field schedule string m h dom mon dow | Very active, the universal substrate; Vixie/ISC cron, cronie, dcron etc. | https://man7.org/linux/man-pages/man5/crontab.5.html |
| Quartz cron (6-/7-field) | ~2001 (Quartz Java scheduler) | OpenSymphony → Terracotta → Software AG; current Quartz 2.3.x and Quartz.NET 3.x | Cron with seconds (field 1) and optional year (field 7); adds ?, L, W, # operators | Active, the Java/.NET enterprise scheduler standard | https://www.quartz-scheduler.org/documentation/ |
| Kubernetes CronJob schedule | 2017 (k8s 1.8 beta) → 2021 GA (1.21) | Kubernetes (Google → CNCF) | Standard 5-field cron interpreted by kube-controller-manager; supports @every and @daily aliases | Very active | https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/ |
| GitHub Actions cron | 2019 | GitHub | 5-field cron, UTC-only; schedule: trigger; @yearly/@monthly etc. not supported | Very active, runs millions of jobs/day | https://docs.github.com/actions/using-workflows/events-that-trigger-workflows#schedule |
| AWS EventBridge cron | 2019 (CloudWatch Events → EventBridge rebrand) | AWS | 6-field cron (adds year), uses ? wildcard for day-of-month/day-of-week mutual exclusion | Very active | https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html |
AWS EventBridge rate(...) | 2016 | AWS | Sibling expression to cron: rate(5 minutes), rate(1 hour), rate(7 days) | Active | https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html |
| systemd OnCalendar | 2013 (systemd 212+) | Lennart Poettering / Red Hat / freedesktop.org | Native systemd timer spec: OnCalendar=Mon..Fri *-*-* 09:00:00; superset of cron | Active, the modern Linux replacement for cron in distros that adopted systemd | https://www.freedesktop.org/software/systemd/man/systemd.time.html |
| at(1) time spec | 1979 (V7 Unix) | AT&T Bell Labs | One-shot natural-language time spec: at noon tomorrow, at midnight + 1 week | Active but niche; lives alongside cron | https://man7.org/linux/man-pages/man1/at.1.html |
| Holiday-rules DSLs (Workalendar / python-holidays) | 2014+ | Various OSS projects | Code-defined holiday rules (“first Monday of September”, “Easter + 50 days”) that emit iCalendar | Active, dozens of country-specific rule modules | https://github.com/peopledoc/workalendar |
Tier 3 family table — Sync / transport protocols
| Protocol | First appeared | Origin | Type | Status (2026) | URL |
|---|---|---|---|---|---|
| CalDAV (RFC 4791) | March 2007 | IETF | WebDAV extension for calendar sync; HTTP REPORT/PROPFIND over iCalendar resources | Active, the universal open standard; backbone of Apple Calendar, Thunderbird, Nextcloud, Radicale, Baikal | https://datatracker.ietf.org/doc/html/rfc4791 |
| CardDAV (RFC 6352) | August 2011 | IETF | WebDAV extension for vCard sync | Active, sister to CalDAV | https://datatracker.ietf.org/doc/html/rfc6352 |
| iTIP (RFC 5546) | December 2009 (obsoleted RFC 2446) | IETF | iCalendar Transport-Independent Interoperability Protocol; defines REQUEST/REPLY/REFRESH/CANCEL/COUNTER/DECLINECOUNTER/PUBLISH/ADD methods | Active, the meeting-invite workflow | https://datatracker.ietf.org/doc/html/rfc5546 |
| iMIP (RFC 6047) | December 2010 (obsoleted RFC 2447) | IETF | iCalendar over email — the actual text/calendar; method=REQUEST MIME body in meeting-invite emails | Very active — every Outlook/Gmail meeting invite in your inbox is iMIP | https://datatracker.ietf.org/doc/html/rfc6047 |
| JMAP for Calendars | Internet-Draft (draft-ietf-jmap-calendars-26, expires May 2026) | Fastmail / IETF JMAP WG | JSON-RPC sync protocol over JSCalendar; intended CalDAV replacement | In progress, not yet RFC; Fastmail ships production support | https://datatracker.ietf.org/doc/draft-ietf-jmap-calendars/ |
| JMAP for Contacts | Internet-Draft | Fastmail / IETF JMAP WG | JSON-RPC sync protocol over JSContact; intended CardDAV replacement | In progress | https://jmap.io/spec.html |
| Microsoft Exchange Web Services (EWS) | 2007 (Exchange 2007) | Microsoft | XML SOAP-based calendar/mail/contact API; proprietary | Legacy — Microsoft has deprecated EWS in favour of Microsoft Graph for cloud Exchange Online (announced retirement 2026) | https://learn.microsoft.com/exchange/client-developer/exchange-web-services/exchange-web-services-reference-for-exchange |
| Microsoft Graph (calendar/contact) | 2015 | Microsoft | REST + JSON event/contact resources; OAuth 2.0 | Very active, the strategic API for Microsoft 365 | https://learn.microsoft.com/graph/api/resources/event |
| Google Calendar API | 2011 (v3) | REST + JSON event resources | Very active | https://developers.google.com/calendar/api/v3/reference | |
| Google People API (contacts) | 2017 (replaced Contacts API) | REST + JSON person resources | Active | https://developers.google.com/people |
Tier 3 family table — Time-zone databases & sub-DSLs
| Format | First appeared | Origin | Type | Status (2026) | URL |
|---|---|---|---|---|---|
| IANA tzdata (Olson DB) | 1986 (Arthur David Olson, NIH) → IANA-stewarded since 2011 | A. D. Olson, P. Eggert, et al. | Authoritative time-zone rules database; Rule, Zone, Link lines define DST/UTC-offset history per IANA TZID | Very active; current release 2026b (April 22, 2026, after 2026a’s Moldova DST correction); 5–10 releases/year | https://www.iana.org/time-zones |
| IANA TZID strings | 1986 (Olson DB) | Olson | Continent/City naming convention: America/New_York, Europe/London, Asia/Tokyo, Pacific/Auckland | Active, the canonical time-zone identifier | https://www.iana.org/time-zones |
| POSIX TZ string | 1988 (POSIX.1) | IEEE / The Open Group | Minimal embedded TZ format: EST5EDT,M3.2.0,M11.1.0 | Active, used by C tzset(), embedded systems, and as a fallback in IANA tzdata for far-future rules | https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html#tag_08_03 |
| DTSTART / DTEND / DURATION | 1998 (RFC 2445) | IETF | Time-anchor sub-DSL within iCalendar; can be DATE-only, DATE-TIME, or DATE-TIME with TZID | Active, mandatory in every VEVENT | https://datatracker.ietf.org/doc/html/rfc5545#section-3.8.2 |
Total entries: 25.
Notable threads
-
iCalendar (RFC 5545) is one of the most-deployed text formats on Earth. Every meeting invitation in Outlook, Gmail, Apple Calendar, Thunderbird, Zoom, Teams, Notion, etc. is iCalendar bytes flying around — usually as an iMIP (RFC 6047)
text/calendar; method=REQUESTMIME part inside an email, or as a CalDAV (RFC 4791)REPORTresponse. ~28 years of stability with one major revision (2009: RFC 2445 → RFC 5545) and one structural successor (2021: JSCalendar / RFC 8984). The format’s vertical-bar line-folding (75-octet limit, leading-space continuation) is famously irritating to parse, but the install base makes it impossible to deprecate. -
The RRULE recurrence DSL is the hardest part of any calendar implementation. Roughly 30 keywords (
FREQ,BYDAY,BYMONTHDAY,BYMONTH,BYSETPOS,BYWEEKNO,BYYEARDAY,INTERVAL,COUNT,UNTIL,WKST, …), and the interaction betweenBYxxxrules is non-obvious — RFC 5545 §3.3.10 includes a 6-page table of howBYxxxparts expand or limit one another. RRULE can express things like “the third Thursday of each month except December” (FREQ=MONTHLY;BYDAY=3TH;BYMONTH=1,2,3,4,5,6,7,8,9,10,11) or “the last weekday of every quarter” (FREQ=YEARLY;BYMONTH=3,6,9,12;BYDAY=MO,TU,WE,TH,FR;BYSETPOS=-1). Most calendar UIs expose only a tiny subset; the full expressiveness is rarely advertised. -
JSCalendar / JSContact (2021/2024) as the long-overdue JSON refresh. RFC 8984 (Stepanek/Jenkins, July 2021) and RFC 9553 (May 2024) replace the line-folded text format with idiomatic JSON, with full round-trip mapping back to iCalendar/vCard preserved (RFC 9554 provides the vCard ↔ JSContact map). Fastmail and Apple lead adoption; Google and Microsoft remain on iCalendar/CalDAV. The IETF CALEXT WG charter requires extensions to define both representations. JSCalendar 2.0 (calext-jscalendarbis-15) is in late draft as of 2026.
-
Cron’s universality from 1975 to 2026. The 5-field cron syntax originated in V7 Unix (Brian Kernighan) and Vixie cron (Paul Vixie, 1987), and has been carried unchanged through every Unix, Linux distro, BSD, container orchestrator, CI/CD platform, and FaaS runtime since. Quartz (Java, 2001) added seconds + year and Sunday=1 day-of-week (vs. Unix’s Sunday=0); AWS EventBridge (2016) adopted Quartz-style 6-field cron with
?wildcards; Kubernetes CronJob (2017+) stayed strict 5-field; GitHub Actions (2019) is 5-field UTC-only. Despite many proposed replacements, base 5-field cron remains the lowest common denominator. -
systemd OnCalendar as cron’s modern successor on Linux. systemd timers (2013, systemd 212+) introduced an
OnCalendar=syntax that is a superset of cron with cleaner semantics:OnCalendar=Mon..Fri *-*-* 09:00:00, full IANA-TZID awareness viaPersistent=, randomized delays viaRandomizedDelaySec=, and cleaner--monotonicboot-relative timers. Most major distros (Fedora, Arch, Debian, Ubuntu) ship systemd timers as the default replacement for cron; Alpine and OpenWrt remain cron-first. Cron is not going away in <10 years, but new code increasingly targets systemd.timer or container-orchestrator schedules instead. -
IANA tzdata as a structured language. The Olson DB
RuleandZonelines are themselves a small DSL describing every legislative time-zone rule on Earth:Rule USA 1967 2006 - Apr lastSun 2:00 1:00 Ddeclares that from 1967 to 2006, USA DST began on the last Sunday of April at 02:00 local with a 1-hour offset called “D”. Releases happen 5–10 times per year, every time a government changes a DST boundary, abolishes DST, or renames a zone. Current release: 2026b (April 22, 2026), after 2026a (March 2026) corrected Moldova’s upcoming clock transition. The data is consumed by glibc, musl, Go’stime/tzdata, Javatzupdater, .NETTimeZoneInfo, Pythonzoneinfo, Rustchrono-tz, and effectively every operating system on Earth. -
POSIX TZ strings vs IANA tzdata: minimal vs rich. POSIX TZ (
EST5EDT,M3.2.0,M11.1.0) is the minimal embedded format: standard-time abbreviation + offset, optional DST abbreviation + DST start/end rules. IANA tzdata is the rich, historically-accurate database. POSIX TZ cannot express historical changes (e.g. that the USA only adopted DST in 1966), and is used today mostly as an embedded fallback in IANA tzdata files for “future rules beyond the data” and in tiny embedded systems where the full tzdata blob is too large. -
The “DST is a programming hazard” tradition. Nearly every calendar bug ever filed traces to DST, time-zone math, or the spring-forward “non-existent local time” / fall-back “ambiguous local time” cases. Examples: Samoa’s 2011 jump across the date line (skipping December 30 entirely); Turkey’s 2016 abrupt DST abolition; Russia’s repeated DST policy reversals; Brazil’s 2019 DST abolition; Kazakhstan’s 2024 unification onto UTC+5. Calendar libraries (
zoneinfoin Python,java.timein Java,Temporalin JS,chrono-tzin Rust) all emphasize “always store in UTC, only convert at the edges” — and that pattern only works because IANA tzdata exists. -
vCard’s contact-card resilience. Versit Consortium (1995), IETF RFC 2426 (1998), RFC 6350 (2011, version 4.0), and now JSContact (RFC 9553, 2024) — vCard has survived 30+ years of contact-management upheaval (PalmPilot → BlackBerry → iPhone → Google Contacts → Microsoft 365 People → Fastmail). Every smartphone exports/imports vCard (.vcf) files; every business-card scanner emits vCard; every CRM-to-mailclient handoff goes through vCard or jCard. The format is close to iCalendar in syntax (line-folded
BEGIN:VCARD/END:VCARDblocks) and shares the same vObject heritage. -
Holiday calendars as a meta-language. Workalendar (Python), python-holidays, dateutil, .NET’s
Nager.Date, JavaScript’sdate-holidays, Ruby’sholidaysgem — these libraries express country-specific holiday rules in code (“US Labor Day = first Monday of September”, “UK Spring Bank Holiday = last Monday of May”, “Japanese Coming-of-Age Day = second Monday of January”, “Easter + 50 days = Pentecost”) and emit iCalendar VEVENT streams. The rule definitions themselves are a small embedded DSL — typically a Python class with methods likeget_first_monday_of(month)— and stay in sync with parliamentary changes (e.g. UK’s 2022 Queen’s Platinum Jubilee bank holiday, Japan’s 2019/2020 Emperor’s enthronement holidays).
Citations
- iCalendar (RFC 5545, Sept 2009): https://datatracker.ietf.org/doc/html/rfc5545
- iCalendar predecessor (RFC 2445, Nov 1998): https://datatracker.ietf.org/doc/html/rfc2445
- vCard 4.0 (RFC 6350, Aug 2011): https://datatracker.ietf.org/doc/html/rfc6350
- jCard JSON vCard (RFC 7095, Jan 2014): https://datatracker.ietf.org/doc/html/rfc7095
- xCard XML vCard (RFC 6351, Aug 2011): https://datatracker.ietf.org/doc/html/rfc6351
- CalDAV (RFC 4791, March 2007): https://datatracker.ietf.org/doc/html/rfc4791
- CardDAV (RFC 6352, Aug 2011): https://datatracker.ietf.org/doc/html/rfc6352
- CalDAV/CardDAV service discovery (RFC 6764): https://datatracker.ietf.org/doc/html/rfc6764
- iTIP (RFC 5546, Dec 2009): https://datatracker.ietf.org/doc/html/rfc5546
- iMIP (RFC 6047, Dec 2010): https://datatracker.ietf.org/doc/html/rfc6047
- JSCalendar (RFC 8984, July 2021): https://datatracker.ietf.org/doc/html/rfc8984
- JSCalendar 2.0 draft (calext-jscalendarbis-15, expires Aug 2026): https://datatracker.ietf.org/doc/draft-ietf-calext-jscalendarbis/
- JSContact (RFC 9553, May 2024): https://datatracker.ietf.org/doc/html/rfc9553
- vCard ↔ JSContact mapping (RFC 9554): https://datatracker.ietf.org/doc/html/rfc9554
- VAVAILABILITY (RFC 7953, Aug 2016): https://datatracker.ietf.org/doc/html/rfc7953
- JMAP core (RFC 8620, July 2019): https://datatracker.ietf.org/doc/html/rfc8620
- JMAP Calendars Internet-Draft (draft-26, expires May 2026): https://datatracker.ietf.org/doc/draft-ietf-jmap-calendars/
- IANA Time Zone Database (tzdata 2026b, April 22, 2026): https://www.iana.org/time-zones
- POSIX TZ string spec (POSIX.1-2017 §8.3): https://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
- POSIX
crontab(5): https://pubs.opengroup.org/onlinepubs/9699919799/utilities/crontab.html - Quartz Cron Trigger tutorial: https://www.quartz-scheduler.org/documentation/quartz-2.3.0/tutorials/crontrigger.html
- Quartz.NET 3.x cron triggers: https://www.quartz-scheduler.net/documentation/quartz-3.x/tutorial/crontriggers.html
- Kubernetes CronJob: https://kubernetes.io/docs/concepts/workloads/controllers/cron-jobs/
- GitHub Actions schedule trigger: https://docs.github.com/actions/using-workflows/events-that-trigger-workflows#schedule
- AWS EventBridge Scheduler types (cron/rate/one-time): https://docs.aws.amazon.com/scheduler/latest/UserGuide/schedule-types.html
- systemd.time(7) — OnCalendar/timespan: https://www.freedesktop.org/software/systemd/man/systemd.time.html
- Microsoft Graph calendar event resource: https://learn.microsoft.com/graph/api/resources/event
- Google Calendar API v3 events: https://developers.google.com/calendar/api/v3/reference/events
- Workalendar (holiday-rule library): https://github.com/peopledoc/workalendar
- python-holidays: https://github.com/vacanza/holidays