Catch timezone bugs with ESLint
Keep new Cloudflare Workers code on the same timezone policy. Pair @rdlabo/workers-timezone with @rdlabo/eslint-plugin-rules to catch host-local Date / Intl operations and request-scoped initialization.
For a runnable demo of both packages, start with Try conversions and lint.
Enable the companion preset
This example uses Node.js 24. In an app using @rdlabo/workers-timezone, install the lint dependencies:
npm install --save-dev eslint@10 @eslint/js@10 typescript@6 typescript-eslint@8 @rdlabo/eslint-plugin-rules@22
Add the timezone preset and typed linting to eslint.config.mjs. The TypeScript files you lint must be included in the app's tsconfig.json.
import { dirname } from 'node:path';
import { fileURLToPath } from 'node:url';
import eslint from '@eslint/js';
import tseslint from 'typescript-eslint';
import rdlabo from '@rdlabo/eslint-plugin-rules/typescript';
export default tseslint.config(
eslint.configs.recommended,
{
files: ['**/*.ts'],
extends: [...tseslint.configs.recommendedTypeChecked],
languageOptions: {
parserOptions: {
projectService: true,
tsconfigRootDir: dirname(fileURLToPath(import.meta.url)),
},
},
plugins: { '@rdlabo/rules': rdlabo },
},
...rdlabo.configs['workers-timezone/recommended'],
);
Keep your existing configuration entries when merging this setup. The separate workers/recommended preset does not enable timezone checks.
Catch a host-local date
This reads the host's calendar date instead of your application's:
const instant = new Date('2026-01-01T15:00:00Z');
console.log(instant.getDate());
Use the library to select the calendar timezone:
import { toLocalDate } from '@rdlabo/workers-timezone';
const instant = new Date('2026-01-01T15:00:00Z');
console.log(toLocalDate(instant, 'Asia/Tokyo'));
// 2026-01-02
no-implicit-timezone also reports supported Intl formatting calls without an explicit timeZone. UTC methods and toISOString() remain available for instant-based operations.
Keep initialization out of requests
initialize-timezone-at-module-scope reports this:
import { initializeTimezone } from '@rdlabo/workers-timezone';
export function handleRequest() {
initializeTimezone({ timeZone: 'Asia/Tokyo' });
}
Initialize during module evaluation instead:
import { initializeTimezone } from '@rdlabo/workers-timezone';
initializeTimezone({ timeZone: 'Asia/Tokyo' });
For a user's timezone, pass an explicit argument to the conversion. The initialization rule checks each file; it does not enforce a single initialization across the entire app.
Run it in CI
After installing dependencies, run:
npx eslint 'src/**/*.ts' --max-warnings 0
Adjust the source path for your app. Keep timezone tests for DST and calendar boundaries: static checks cover recognizable operations, not every dynamic value.
See the Date / Intl rule, initialization rule, and timezone behavior.