Calendar: keep the UTC zone of a series that starts in UTC #305

Merged
jcoffey-dev merged 1 commits from fix/recurring-event-time-zone into main 2026-11-06 20:27:41 +00:00
Owner

Fixes #303.

It's narrower than the issue says: only series whose start is written in UTC (DTSTART:...Z, which is how a JMAP timeZone: Etc/UTC event is stored) were affected. Series in a named zone such as America/New_York, floating series and one-off events were already right. Tried on 27.1-rc.9 with each kind, read with America/Phoenix, Etc/UTC and no zone.

The cause is in calcard. It took the start zone from the TZID, or the default when there's none, and the server passes floating as the default. So every instance of a UTC rule was stored floating, and get, query, CalDAV time ranges, free/busy and alarms all read the series in whatever zone the request asked for.

  • vendor/calcard: a DTSTART with an offset keeps that zone (calcard 0.4 does the same). Logged in its VENDORED.md.
  • groupware expand and alarms: a floating range whose component starts with an offset is read in that zone. That covers series stored before this change, with no reindex. Recurrence ids don't move: they're built from the local time, which is the same either way.
  • CalendarEvent/get: an occurrence of a UTC series says Etc/UTC, as its base event does, rather than the request's zone.
  • CalendarEvent/get also worked out the base event's utcStart after taking the event out of its data, so the expansion couldn't see the DTSTART. It runs first now.

Tests: start_zone_tests in calcard and utc_series_ignores_the_request_zone in groupware (new data, old floating-stored data, a floating series); each fails without its part of the change. The JMAP instance test now reads a UTC series in Phoenix and UTC. JMAP and WebDAV suites pass locally.

Also ran the build against the same probe events as on rc.9, both freshly written and in a copy of the store rc.9 wrote: every UTC series now comes back at 18:00Z labeled Etc/UTC in every request zone, and the rest is unchanged.

Not changed: occurrences of a floating series still take the request's zone as their label, as before.

Fixes #303. It's narrower than the issue says: only series whose start is written in UTC (`DTSTART:...Z`, which is how a JMAP `timeZone: Etc/UTC` event is stored) were affected. Series in a named zone such as America/New_York, floating series and one-off events were already right. Tried on 27.1-rc.9 with each kind, read with America/Phoenix, Etc/UTC and no zone. The cause is in calcard. It took the start zone from the TZID, or the default when there's none, and the server passes floating as the default. So every instance of a UTC rule was stored floating, and get, query, CalDAV time ranges, free/busy and alarms all read the series in whatever zone the request asked for. - `vendor/calcard`: a DTSTART with an offset keeps that zone (calcard 0.4 does the same). Logged in its VENDORED.md. - `groupware` expand and alarms: a floating range whose component starts with an offset is read in that zone. That covers series stored before this change, with no reindex. Recurrence ids don't move: they're built from the local time, which is the same either way. - `CalendarEvent/get`: an occurrence of a UTC series says Etc/UTC, as its base event does, rather than the request's zone. - `CalendarEvent/get` also worked out the base event's `utcStart` after taking the event out of its data, so the expansion couldn't see the DTSTART. It runs first now. Tests: `start_zone_tests` in calcard and `utc_series_ignores_the_request_zone` in groupware (new data, old floating-stored data, a floating series); each fails without its part of the change. The JMAP instance test now reads a UTC series in Phoenix and UTC. JMAP and WebDAV suites pass locally. Also ran the build against the same probe events as on rc.9, both freshly written and in a copy of the store rc.9 wrote: every UTC series now comes back at 18:00Z labeled Etc/UTC in every request zone, and the rest is unchanged. Not changed: occurrences of a floating series still take the request's zone as their label, as before.
jcoffey-dev added 1 commit 2026-11-06 20:12:04 +00:00
Calendar: keep the UTC zone of a series that starts in UTC
ci / fork-checks (pull_request) Skipped
ci / build (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 15m7s
21d859aa4c
A recurring event whose DTSTART is written in UTC ("...Z", as a JMAP
timeZone of Etc/UTC is stored) came back in the zone of the request:
read with America/Phoenix, an 18:00 UTC weekly event said 01:00Z and,
for its occurrences, America/Phoenix. Named-zone and floating series and
one-off events were right.

calcard took a component's start zone from its TZID or the default, and
the server's default is floating, so every instance of a UTC rule was
stored floating and read in the request's zone. The DTSTART's own
offset now wins, as in calcard 0.4. Series already stored floating are
read in their DTSTART's offset when it has one, so no reindex is needed.
Occurrences of a UTC series are labeled Etc/UTC like the base event, and
the base event's utcStart is worked out before the event is taken out of
its data.

Fixes #303.
jcoffey-dev merged commit 4f56df5bfd into main 2026-11-06 20:27:41 +00:00
jcoffey-dev deleted branch fix/recurring-event-time-zone 2026-11-06 20:27:41 +00:00
Sign in to join this conversation.