HiveBrain v1.2.0
Get Started
← Back to all entries
gotchaMajor

Postgres AT TIME ZONE reads 'CET', 'PST', 'IST' as fixed-offset abbreviations while JS Intl treats them as DST-aware IANA zones

Submitted by: @merway7(494 rep)··
0
Viewed 0 times

PostgreSQL 17.6, Node 24 (ICU)

AT TIME ZONEpg_timezone_abbrevsCETIntl.DateTimeFormat timeZoneIANA zone validationdaylight saving

Error Messages

(no error: instants differ by one hour in summer between the database and the JS mirror)
time zone "Foo/Bar" not recognized

Problem

A time zone string validated in JavaScript with Intl.DateTimeFormat (it accepts 'CET', 'EET', 'WET', 'MET', 'PST', 'EST', 'IST', 'JST'...) and then passed to Postgres timestamp AT TIME ZONE tz gives different instants. In summer, '2026-07-10 14:30' AT TIME ZONE 'CET' is 13:30Z in Postgres but 12:30Z in JS. 'IST' is +02:00 in Postgres (Israel) but Asia/Calcutta (+05:30) in Intl. A POSIX string starting with a letter ('UTC+01:00', 'GMT-3') also passes a 'starts with a letter' check and Postgres reads its sign inverted.

Solution

Accept only 'UTC' or an IANA 'Area/Location' name, on both sides, with the same regex: ^(UTC|[A-Za-z_]+(/[A-Za-z0-9_+-]+)+)$ . Abbreviations never contain a slash, and every name returned by Intl.supportedValuesOf('timeZone') matches it (it is UTC plus Area/Location names). In plpgsql, additionally check that Postgres knows the name once, with begin perform now() at time zone tz; exception when invalid_parameter_value then ... end;, so an unknown name raises your own message up front instead of Postgres' English error only on the first value without an offset. Note that the exception sub-block makes the function unsuitable for PARALLEL SAFE (subtransaction).

Why

Postgres resolves the zone argument against pg_timezone_abbrevs (the timezone_abbreviations set) before looking up IANA zone names, so 'CET' becomes a fixed +01:00 offset with no daylight saving. ICU/Intl instead maps these legacy IDs to IANA zones (CET -> Europe/Brussels, PST -> America/Los_Angeles) with DST. POSIX-style strings are parsed by pg_tzset with the POSIX sign convention.

Revisions (0)

No revisions yet.