Skip to content

fix(calendar): prefix TZID with '/' to use globally-defined IANA timezone identifiers#60588

Draft
miaulalala wants to merge 1 commit into
masterfrom
fix/calendar-event-builder-vtimezone
Draft

fix(calendar): prefix TZID with '/' to use globally-defined IANA timezone identifiers#60588
miaulalala wants to merge 1 commit into
masterfrom
fix/calendar-event-builder-vtimezone

Conversation

@miaulalala
Copy link
Copy Markdown
Contributor

Summary

  • CalendarEventBuilder::toIcs() emits DTSTART;TZID=Europe/Berlin:... but never includes a VTIMEZONE component
  • Sabre's iTIP broker only copies existing VTIMEZONE components into invite emails — so without one, attendees receive an ICS with a dangling TZID reference
  • Some clients (e.g. Grommunio) fail to resolve the timezone and display the wrong time (reported in Meeting invites miss VTIMEZONE block in attached ICS file spreed#18039)

RFC 5545 §3.2.19 allows a leading / on a TZID to indicate a globally-defined IANA identifier, which is valid without a VTIMEZONE block. This PR applies that prefix to DTSTART and DTEND before serialisation. UTC datetimes (Z-suffix, no TZID) are unaffected.

Test plan

  • php vendor-bin/phpunit/vendor/phpunit/phpunit/phpunit --no-coverage -c tests/phpunit-autotest.xml tests/lib/Calendar/CalendarEventBuilderTest.php — all 8 tests pass
  • testToIcsWithTimezone asserts DTSTART;TZID=/Europe/Berlin:, no BEGIN:VTIMEZONE, and matches the full fixture
  • testToIcsWithUtcIsUnchanged asserts UTC datetimes are not altered

Fixes: nextcloud/spreed#18039 (workaround on the Talk side is in nextcloud/spreed#XXXX)

🤖 Generated with Claude Code

@miaulalala miaulalala requested review from Altahrim, ArtificialOwl, artonge and salmart-dev and removed request for a team May 19, 2026 17:52
…zone identifiers

Without a leading '/', a TZID like 'Europe/Berlin' in DTSTART/DTEND requires an
accompanying VTIMEZONE component (RFC 5545 §3.2.19). CalendarEventBuilder never
emits VTIMEZONE, so Sabre's iTIP broker had nothing to copy into invite emails —
leaving recipients with a dangling TZID reference that clients like Grommunio
misinterpret as an unknown timezone.

Prepending '/' makes the TZID a globally-defined IANA identifier, which is valid
without VTIMEZONE and is universally understood. UTC datetimes (Z suffix, no TZID)
are unaffected.

AI-Assisted-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Signed-off-by: Anna Larch <anna@nextcloud.com>
@miaulalala
Copy link
Copy Markdown
Contributor Author

/backport to stable34

@miaulalala
Copy link
Copy Markdown
Contributor Author

/backport to stable33

@miaulalala
Copy link
Copy Markdown
Contributor Author

/backport to stable32

@miaulalala
Copy link
Copy Markdown
Contributor Author

Once sabre-io/vobject#757 is fixed and the updated Sabre VObject version is vendored into Nextcloud, this PR can be reverted — the / prefix will be emitted correctly by Sabre itself during serialisation.

@tcitworld
Copy link
Copy Markdown
Member

It would be nice if someone made sure this doesn't cause regressions in other popular clients that don't understand correctly globally-defined timezone identifiers.

In any case, the spec says VTIMEZONE components are still required, some implementations are just tolerating using IANA-registered TZID (which is nice, but not an expectation).

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

Labels

3. to review Waiting for reviews backport-request bug feature: caldav Related to CalDAV internals

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Meeting invites miss VTIMEZONE block in attached ICS file

3 participants