Skip to content

CalendarEvent: optional timezone, the IANA zone the wall clock was meant in - #1209

Open
EgorPPS wants to merge 1 commit into
mainfrom
meshenger/calendarevent-timezone
Open

EgorPPS wants to merge 1 commit into
mainfrom
meshenger/calendarevent-timezone

Conversation

@EgorPPS

@EgorPPS EgorPPS commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

CalendarEvent (880e8400-e29b-41d4-a716-446655440099) has start, end and isAllDay, but no way to say which zone the wall clock was meant in. This adds one optional string. It is additive and changes nothing for existing readers or existing events.

An offset is not a zone

The obvious objection is that start/end already carry an offset, so a zone is redundant. It is not, in two directions:

  • An offset does not identify a zone. +02:00 is Europe/Amsterdam and Africa/Johannesburg alike. From a stored event you cannot get back to the zone.
  • A zone does not have one offset. Amsterdam is +02:00 in July and +01:00 in January. The offset is the consequence of a zone at one instant.

So the offset answers "what instant", and only a zone answers "what did the person mean, and what will they mean next year". Two things need the latter:

  1. Re-rendering an event in the zone it was scheduled in — a 09:00 meeting in Amsterdam read from Tokyo should still be showable as the 09:00 it was agreed to be, not only as 16:00 local.
  2. Recurrence across a DST boundary — "every Monday at 09:00 Amsterdam" is a different instant before and after the clocks change. Without the zone there is nothing to recompute from. CalendarEvent has no recurrence field today, which is exactly why this matters now rather than later: the value is lost at every write, so when recurrence does arrive there will be nothing to reconstruct it from, while the envelopes will still be there.

Why this is a pull request and not a private field

The schema is "additionalProperties": false. Meshenger has been writing timezone onto it, which does not extend the schema — it makes our envelopes fail strict validation. Writing it privately is the thing to avoid: two applications inventing their own name for the same fact is how a shared schema splits. So the field comes here, where every other calendar application gets it too, under one name.

This is the same route as #1183 (File: optional width/height), for the same reason.

Shape

Optional string, holding an IANA zone name (Europe/Amsterdam). Deliberately not an enum — the IANA database changes, and a schema that enumerates zones is wrong the next time a country redefines one. A reader that does not recognise the name should fall back to the offset in start, which is unchanged and still correct.

Discussed with the DigitalSelf platform before opening, which is where the "lost at every write" argument came from.

…ant in

An offset is not a zone. The offset in start/end is the consequence of a
zone at one instant: +02:00 is both Europe/Amsterdam and
Africa/Johannesburg, and Amsterdam's own offset differs either side of a
DST boundary. So the zone cannot be recovered from a stored event, and
an application that wants to re-render an event in the zone it was
scheduled in -- or place a recurrence correctly once the clocks change
-- has nowhere to read it from.

The field is optional and additive: a reader that does not know it is
unaffected, and an event without it is exactly as valid as before.

Raised because the schema is additionalProperties:false, so writing this
privately would make the envelopes fail strict validation instead of
extending the schema -- the honest route is here.
@EgorPPS
EgorPPS requested a review from coodos as a code owner October 28, 2026 09:32
@coderabbitai

coderabbitai Bot commented Oct 28, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

Run configuration
  • Source mode: Auto
  • Repository: Unavailable
  • Branch: Unavailable
  • File: No configuration file from this repository applied
  • Commit: Unavailable
  • Layers: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: c6e0dbc4-b0ab-4e7e-8cdd-3effa02327f0
  • Autofix · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant