Fix events_fetch: date-only inputs silently ignored; missing @id on events#175
Open
ole-lilienthal wants to merge 2 commits into
Open
Fix events_fetch: date-only inputs silently ignored; missing @id on events#175ole-lilienthal wants to merge 2 commits into
ole-lilienthal wants to merge 2 commits into
Conversation
Without an identifier, Event values produced from EKEvent encoded as JSON-LD blank nodes. Two events with the same name/dates/calendar serialised to byte-identical objects, and downstream JSON-LD-aware consumers collapsed them into a single node. Symptom: events_fetch appeared to silently filter out duplicate-named events. Populate Event.identifier from EKEvent.eventIdentifier in both events_fetch and events_create so each event carries a stable @id, matching what Ontology already does for Person (CNContact.identifier) and ItemList (EKCalendar.calendarIdentifier).
ISO8601DateFormatter.lenientDate(fromISO8601String:) ran a regex to
decide whether the input already carried a timezone offset and thus
should not be re-parsed in local time. The regex
#"([Zz]|[+-]\\d{2}(:?\\d{2})?)$"# matches the trailing -DD of any
bare yyyy-MM-dd date — "2026-06-15" looks like it ends with a -15
offset — so date-only inputs returned nil instead of falling through
to the "yyyy-MM-dd" DateFormatter fallback.
In events_fetch this manifested as a silent regression: when the
caller passed e.g. start="2026-06-02", end="2026-06-15", parsing
failed for both, hasStart/hasEnd stayed false, and the tool fell back
to its 'now → now + 1 week' default range. The user saw events from
the current week and assumed events past that point had been filtered
out (in this case two same-name events where only the earlier one was
in the default range).
Gate the timezone-suffix check on dateString.count > 10 so it can't
fire on a bare yyyy-MM-dd. The day component can no longer collide
with the offset branch of the regex; date-only inputs now reach the
"yyyy-MM-dd" fallback as intended.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Two related fixes for the Calendar service's
events_fetchtool, found while investigating reports of "two events with the same name only return one".1. Date-only
start/endinputs are silently ignoredISO8601DateFormatter.lenientDate(fromISO8601String:)checks whether the input already carries a timezone offset to decide whether to fall through to local-time parsing. The check is a regex:That
[+-]\d{2}branch matches the trailing-DDof any bareyyyy-MM-dddate —"2026-06-15"looks like it ends with a-15offset — so date-only inputs returnnilinstead of falling through to the"yyyy-MM-dd"DateFormatterfallback that already exists below.In
Calendar.swift'sevents_fetch,parsedLenientISO8601Datereturningnilis silent:hasStart/hasEndstayfalseand the tool falls back to its defaultnow → now + 1 weekrange. So a call like{ "start": "2026-06-02", "end": "2026-06-15" }actually executes as
start = now, end = now + 1 week. The caller observes events from the current week only and reasonably reads it as "events outside that range got filtered" — which, when two events share a name and only one falls inside the default range, looks like "events with duplicate names get deduped".Fix: gate the timezone-suffix check on
dateString.count > 10so it can't fire on a bareyyyy-MM-dd. Date-only inputs now reach the existing"yyyy-MM-dd"fallback parser as intended. ISO datetimes with timezone offsets continue to short-circuit as before.2.
EventfromEKEventcarries no@idOntology.Event(_ event: EKEvent)doesn't setidentifier, so emitted JSON-LD lacks@id. Other types in the same package do set it:Person.init(_ contact: CNContact)usescontact.identifier;ItemList.init(_ calendar: EKCalendar)usescalendar.calendarIdentifier.events_fetchandevents_createnow populate it fromEKEvent.eventIdentifierbefore encoding, matching that convention. Stable@ids let downstream JSON-LD-aware consumers reliably distinguish two events with identical name/dates rather than treating them as the same blank node.Fix #2 was found first; fix #1 turned out to be the actual cause of the reported symptom. Both are kept because each is correct on its own.
Verification
yyyy-MM-ddreturnednilfromlenientDatebefore and now parses to local midnight; ISO datetimes withZ/+HH:MM/-HH:MMsuffixes still parse as before.imcp-serverover JSON-RPC with date-onlystart/endarguments now returns events covering the requested range instead of stopping at the default-range boundary.swift format lint --strict --recursive .passes.Files
App/Extensions/Foundation+Extensions.swift— gate the timezone-suffix regex on input length > 10.App/Services/Calendar.swift— setEvent.identifierfromEKEvent.eventIdentifierinevents_fetchandevents_create.