Multi-day and recurring events now keep their full span, land on the correct local day, and expose complete start/end data to templates.
What's new
- Four new fields are available from
getEvents()without changing any existing field:startDateTimeandendDateTime— full ISO 8601 values with UTC offsets;endUtime— the event's end as a Unix timestamp, mirroringutime;allDay—truefor all-day (VALUE=DATE) events.
- “Show ongoing” now defaults to on for newly added calendars. Multi-day events therefore appear on each day they span without requiring users to discover the setting first. Existing calendar settings are not migrated or changed.
- The README's Full Calendar example now preserves multi-day ends using
endUtimeand passesallDaythrough. New documentation shows how to render full date ranges and handle all-day events' exclusiveDTEND.
What's fixed
Thanks to @spi43984 for testing the betas and providing precise provider examples.
- Recurring, one-off, and multi-day events now use one occurrence-selection pipeline. This fixes:
- overnight and multi-day recurrences losing their duration or later days;
- recurring overrides disappearing or suppressing the wrong occurrence;
EXDATEremoving every occurrence on the same day instead of one instance;- DATE and DATE-TIME
RDATEoccurrences being omitted; - all-day recurrences shifting dates in positive UTC offsets or across spring-forward days;
- duplicate emission, sparse queries returning intervening events, and parsed calendars being mutated during filtering.
- Distinct events are no longer lost during deduplication. Identity now includes UID, recurrence identity, start, and end instead of relying on display text and time alone.
- Broken all-day re-exports are recovered. Same-timezone events encoded as exactly
00:00:00through23:59:59are exposed as all-day ranges with correct inclusive dates and exclusive ends. - Missing metadata is deterministic. Events without
CREATEDorLAST-MODIFIEDno longer receive a different timestamp on every call. - Calendar settings dialogs no longer leak unsaved changes. Adding, editing, or cancelling a calendar no longer mutates defaults or saved toggle values before Save.
Behavior and compatibility
- Timed recurring events are assigned to the day on which their instant occurs in the user's local timezone, consistently with one-off events and Daily Note queries. Previously they could use the organizer's calendar date.
- Existing
getEvents()signatures, flexible date inputs, output fields,callUrl/callType, markdown output, and saved calendars remain compatible. - The all-day recovery rule is intentionally narrow: start must be exactly
00:00:00, end exactly23:59:59, and both must declare the same timezone. Near-miss timed events and legitimate next-midnight 24-hour events remain timed. - Obsidian 1.12.7 or later is required.
Verification
- Validated through five public betas and a final live Obsidian vault test.
- 119 Jest tests passed in each of 9 host timezones from UTC-11 through UTC+14: 1,071/1,071 total, zero skips.
- 50 compiled-artifact contract tests passed against the shipped bundle; the same final runtime passed that contract in every timezone during the beta cycle.
- The release build, lint gate, artifact provenance attestation, and downloaded release assets all passed verification.
Known limitations
RDATEvalues using thePERIODform are not expanded.- All-day compatibility inference is limited to the reported same-timezone
00:00:00through23:59:59shape. Fractional-second values are invalid RFC 5545 DATE-TIME input; ambiguous next-midnight and23:59:00forms remain timed unless a concrete provider case establishes the intended semantics.
Implementation details: public event date fields #243, settings defaults #245, artifact and override coverage #252, occurrence selection #254, and timezone portability #256.