split recurring event generates Google-style _R UID with wrong timestamp (local time, one month early) instead of a fresh UUID
Summary
When a recurring event is split in Proton Calendar (editing or deleting "this and following events"), the new series is written with a UID of the form <base-id>_R<timestamp>@domain instead of a fresh UUID. Two problems with this:
- The
_R<timestamp>convention is Google Calendar's private internal ID scheme for split recurring series. It is not part of RFC 5545, where UIDs are opaque identifiers and relationships between instances are expressed through RECURRENCE-ID, never by parsing substrings out of an ID. - The timestamp Proton writes into it is incorrect. Google's format uses the UTC start of the split. Proton writes a value one month earlier than the actual series start, in local time rather than UTC.
Examples
From my own exported .ics:
UID:3nhn7bc...veeo_R20260126T153000@google.com
DTSTART;TZID=Europe/Helsinki:20260226T153000 (correct: 20260226T133000Z)
UID:181e5hr...nnug_R20260127T153000@google.com
DTSTART;TZID=Europe/Helsinki:20260227T153000 (correct: 20260227T133000Z)
UID:IHyNtsw...AqeA_R20260709T150000@proton.me
DTSTART;TZID=Europe/Helsinki:20260809T163000 (correct: 20260809T133000Z)
Every _R UID in my file is wrong the same way, 28 of them across 16 series. The third example matters: this affects events created natively in Proton, not only calendars imported from Google. Events in my file that were split years ago while still in Google carry correct UTC timestamps, so the incorrect values were introduced by Proton.
Impact
Google Calendar subscribed to a Proton share link appears to read <base>_R<timestamp> as its own split-series format and reconcile all siblings sharing a base ID into a single recurring family. Because the split timestamps are wrong, the boundaries between links in the chain do not line up, and Google renders an older link instead of the current one.
In my case two weekly series had their end times silently changed, showing 20:00 and 17:00 where the file says 16:30. After I capped the affected series and created replacements, Google displayed both the correct new event and the ghost from the old chain, stacked on the same day.
This was hard to diagnose because the .ics itself is well formed. Distinct UIDs, correct RRULEs, correct DTENDs. Proton's own client renders it correctly, and so did every standard parser I tested it against. Only the UID is anomalous, and it is the one field nobody thinks to check.
Steps to reproduce
- Create a weekly recurring event in Proton Calendar.
- Open a later instance and choose "this and following events", change the end time, save.
- Export the calendar as .ics and inspect the UID of the new series.
Expected: a fresh UUID, as Proton already generates for newly created events.
Actual: <base-id>_R<timestamp>@proton.me with a timestamp one month early and in local time.
Suggested fix
Mint a fresh RFC 5545 UID when splitting a recurring series, matching what Proton already does everywhere else. Imitating another vendor's undocumented internal ID namespace has no upside for interoperability and creates exactly this class of failure with downstream consumers. If a derived identifier is needed for internal linkage, keep it in an X- property rather than in UID, and at minimum correct the timestamp to UTC and to the actual split point.
Workaround for anyone hitting this
Do not use "this and following events" on any calendar that an external client subscribes to. End the series instead, then create a brand new event going forward, which gets a clean UUID.
Happy to supply a sanitized .ics demonstrating the pattern if that helps.