Skip to content

fix: accept basic-format inline offsets in date-time-string time zone ids - #89

Merged
MidnightDesign merged 1 commit into
masterfrom
timezone-basic-offset
Aug 17, 2026
Merged

fix: accept basic-format inline offsets in date-time-string time zone ids#89
MidnightDesign merged 1 commit into
masterfrom
timezone-basic-offset

Conversation

@MidnightDesign

@MidnightDesign MidnightDesign commented Aug 17, 2026

Copy link
Copy Markdown
Owner

Problem

TimeZoneHelper::normalizeTimezoneId() recognized an inline UTC offset in a date-time-string time zone identifier only when it was written with a colon:

$zdt->withTimeZone('2021-08-19T17:30-07:00');  // → '-07:00'
$zdt->withTimeZone('2021-08-19T1730-0700');    // → RangeError: bare datetime without Z, offset, or bracket.

ISO 8601 allows both the extended (±HH:MM) and the basic (±HHMM) spelling of an offset, and TC39 accepts either. test262 lists both in the valid set of relativeto-propertybag-timezone-string-datetime.js; that fixture passed only because the relativeTo path validated the string and then ignored the zone it named.

The fix

One regex. ([+\-]\d{2}:\d{2}) becomes ([+\-])(\d{2}):?(\d{2}), and the three groups are reassembled into the canonical extended form, so the return value is unchanged for input that already parsed.

Scope

Deliberately not touched: Instant.php:713, Instant.php:931 and RelativeTo.php:854 each carry their own copy of this parsing, and all three still reject the basic spelling — which is why Instant::toZonedDateTimeISO('2021-08-19T1730-0700') still throws. That duplication is pre-existing and belongs in its own change.

Verification

PHPStan level 9, Psalm, mago lint/analyze/format all clean. Full suite: 12396 tests, 1032460 assertions, 299 incomplete — identical to master on all three counts.

Split from #82, which is blocked on this: once #82 resolves the zone a relativeTo bag names instead of discarding it, the two relativeto-propertybag-timezone-string-datetime fixtures fail without this fix.

… ids

An inline UTC offset in a date-time-string time zone identifier was only
recognized when spelled with a colon, so "2021-08-19T1730-0700" raised
"bare datetime without Z, offset, or bracket" while the extended spelling
of the same offset resolved. ISO 8601 allows both.
@MidnightDesign MidnightDesign changed the title timezone basic offset fix: accept basic-format inline offsets in date-time-string time zone ids Aug 17, 2026
@MidnightDesign
MidnightDesign merged commit 056f2ba into master Aug 17, 2026
2 checks passed
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