no-implicit-timezone
Prevent implicit host-timezone behavior across Date parsing, construction, access, and Intl formatting.
Cloudflare Workers use UTC as the host local timezone. Code that appeared to use a server's local timezone can therefore change calendar dates or wall-clock values after migration. This rule keeps those operations behind an explicit UTC or IANA-timezone boundary.
Rule details
One rule covers the common escape hatches so applications do not need to discover and configure a collection of Date rules.
| Reported operation | Use instead |
|---|---|
new Date(year, month, ...) |
Date.UTC(...) for UTC, or a timezone-aware wall-clock conversion |
Callable Date() |
Create an instant and format it explicitly |
Local getters/setters such as getDate() and setHours() |
A timezone conversion, or the corresponding getUTC*/setUTC* API when UTC is intended |
toString(), toDateString(), toTimeString() |
Explicit formatting |
Intl.DateTimeFormat or Date#toLocale* without an explicit timeZone |
Add { timeZone: '...' } or another explicit timezone option |
ISO-like date-time literals without Z or ±HH:mm |
Add an offset, or parse them as a timezone-local wall clock |
toISOString(), toJSON(), getTime(), valueOf(), UTC methods, epoch constructors, and date-only YYYY-MM-DD strings are allowed. toISOString() is the correct representation for many instant contracts and is intentionally not banned.
Typed linting is required. The rule verifies that method receivers are the built-in Date, so unrelated objects with methods such as getDate() are not reported. any, unknown, dynamic Intl options (including a dynamic timeZone value), argument spreads among the first two slots of Intl.DateTimeFormat / Date#toLocale* (where the options position is uncertain), dynamic date strings, destructured methods, and spread Date constructor arguments are not guessed at and remain outside static analysis coverage. A trailing spread after a fixed options argument is still checked. A static non-empty timeZone string is accepted; missing options, null options, and an unshadowed global undefined options/timeZone value are reported.
The string check covers structurally ISO-like YYYY-MM-DD[T ]HH:mm[:ss[.fraction]] literals. It detects a missing offset; it is not a calendar or general date-string validator.
Examples
Incorrect
const local = new Date(2026, 0, 2, 9, 0);
const day = instant.getDate();
const label = instant.toLocaleString('ja-JP');
const parsed = new Date('2026-01-02T09:00:00');
Correct
const instant = new Date('2026-01-02T00:00:00Z');
const epoch = instant.getTime();
const iso = instant.toISOString();
const utcDay = instant.getUTCDate();
const label = instant.toLocaleString('ja-JP', { timeZone: 'Asia/Tokyo' });
For @rdlabo/workers-timezone, prefer toLocalDate, toLocalDateTime, and localDateTimeToInstant at business-calendar boundaries.