Skip to content

Fix timezone conversion skipped with DateTimeImmutable - #171

Merged
rlanvin merged 1 commit into
rlanvin:masterfrom
srebb:fix/datetimeimmutable-timezone-conversion
Jul 29, 2026
Merged

Fix timezone conversion skipped with DateTimeImmutable#171
rlanvin merged 1 commit into
rlanvin:masterfrom
srebb:fix/datetimeimmutable-timezone-conversion

Conversation

@srebb

@srebb srebb commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

DateTimeImmutable::setTimezone() returns a new object instead of modifying the receiver, but four call sites discard the return value. When dtstart, until or the occursAt() argument is a DateTimeImmutable, the conversion silently never happens.

  • RRule.php:609rfcString() sets $timezone_name = 'UTC' for an unsupported timezone like +02:00, but $dtstart keeps its original offset, so local time is emitted labelled as UTC.
  • RRule.php:643 / RRule.php:649UNTIL ends up neither in UTC nor on the DTSTART timezone.
  • RRule.php:773occursAt() carries the comment "convert timezone to dtstart timezone for comparison", but the BYHOUR/BYMINUTE/BYSECOND and BYMONTHDAY checks that follow read format() off the unconverted date, so the returned result can be wrong.

DateTimeImmutable::setTimezone() returns a new object instead of
modifying the receiver, so four calls that discarded the return value
never converted anything when dtstart, until, or the occursAt()
argument was immutable.

As a result occursAt() ran its BYHOUR/BYMINUTE/BYSECOND and BYMONTHDAY
checks against the wall clock of the unconverted date, and rfcString()
emitted local time labelled as UTC for DTSTART with an unsupported
timezone such as "+02:00", plus an unconverted UNTIL.

Assigning the return value is a no-op for DateTime, which mutates in
place and returns itself, so existing callers are unaffected. PHP 8.5
surfaces the bug via #[\NoDiscard], but the wrong output occurs on
every supported version.
@srebb

srebb commented Jul 28, 2026

Copy link
Copy Markdown
Contributor Author

Just saw, one of the cases was already requested as MR in #170
Sorry, I just checked the open issues (not the MR) before fixing it.

Explanation and test added in the commit.

@rlanvin
rlanvin merged commit ae7d01a into rlanvin:master Jul 29, 2026
7 checks passed
@rlanvin

rlanvin commented Jul 29, 2026

Copy link
Copy Markdown
Owner

Thank you for adding explanation and tests, this actually helped me a lot to understand what the issue was.

@rlanvin rlanvin mentioned this pull request Jul 29, 2026
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.

2 participants