The Cloudflare Workers runtime does not provide a native mechanism to manually specify a preferred offset (Standard vs. Daylight) for a specific IANA time zone. This is because Intl.DateTimeFormat is a formatting API, not a parsing API; it is designed to be deterministic based on a unique UTC timestamp.
The Nature of the Ambiguity
The "fall back" overlap ambiguity occurs when converting a local time string to a UTC timestamp. However, when using Intl.DateTimeFormat, the process moves in the opposite direction: UTC Timestamp → Local String.
Because the JavaScript Date object is always anchored to a precise UTC epoch, there is no ambiguity during formatting. A single point in UTC time maps to exactly one local time in a given IANA zone. If two different UTC timestamps map to the same local time string during a DST transition, the runtime handles this by simply applying the ICU rules for those specific moments in time.
Likely Explanation of Behavior
Since the V8 ICU implementation follows the ECMAScript Internationalization API specification, the offset is derived automatically from the IANA database based on the UTC timestamp provided. You cannot "force" a Date object to use a specific offset for a zone; the offset is a property of the time and the zone, not a configurable option of the formatter.
Implementation Strategy
To handle DST transitions without importing heavy tzdata libraries, rely on the fact that UTC is the source of truth. If you must resolve which "version" of a local hour a user is referring to, you must capture the offset at the source (the client) and pass that offset to the Worker.
To verify the behavior of a specific transition in your Worker, use a scoped test like this:
const zone = 'America/New_York';
const formatter = new Intl.DateTimeFormat('en-US', {
timeZone: zone,
timeZoneName: 'shortOffset'
});
// Two different UTC times that might result in the same local time
const time1 = new Date('2024-11-03T05:30:00Z');
const time2 = new Date('2024-11-03T06:30:00Z');
console.log(formatter.format(time1));
console.log(formatter.format(time2));
Verification Checklist
- Confirm Input: Ensure you are passing a
Date object (UTC) to the formatter.
- Verify Offset: Include
timeZoneName: 'shortOffset' in your options to see exactly which offset (e.g., GMT-4 vs GMT-5) the runtime has assigned to that timestamp.
Missing Diagnostic Detail: Are you attempting to convert a local string into a Date object, or are you only formatting existing Date objects for display? If you are parsing local strings, Intl.DateTimeFormat cannot help, and you will need to provide the offset explicitly in the input string (ISO 8601) to avoid ambiguity.