Skip to content
rdlabo.devdocs

Try conversions and lint

One instant can belong to different calendar dates. First see that difference, then make ESLint report code that accidentally falls back to the host timezone.

1. Install the pair

Requires Node.js 24 and npm.

mkdir timezone-demo
cd timezone-demo
npm init -y
npm pkg set type=module
npm install @rdlabo/workers-timezone@0.12.2
npm install --save-dev @rdlabo/eslint-plugin-rules@22.1.0 eslint@10 @eslint/js@10 typescript@6 typescript-eslint@8 tsx@4

2. See the calendar date change

Save this as demo.ts. Initialize the application timezone once at module scope; pass a per-call timezone for a user-specific conversion.

import { initializeTimezone, toLocalDate, toLocalDateTime } from '@rdlabo/workers-timezone';

initializeTimezone({ timeZone: 'Asia/Tokyo' });
const instant = new Date('2026-01-01T15:00:00Z');
console.log(toLocalDateTime(instant));
console.log(toLocalDate(instant, 'America/New_York'));
npx tsx demo.ts
2026-01-02 00:00:00
2026-01-01

The same instant is January 2 in Tokyo and January 1 in New York. Add an explicit timezone argument for another city to explore the difference.

3. Make an accidental regression visible

Save this as tsconfig.json so typed linting can find demo.ts:

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "noEmit": true
  },
  "include": ["demo.ts"]
}

Save this as eslint.config.mjs. Keep type-aware configuration scoped to TypeScript files:

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'],
);

Check the correct example:

npx eslint demo.ts

It should exit successfully without diagnostics. Now append this deliberately incorrect line to demo.ts:

console.log(instant.getDate());
npx eslint demo.ts

Expect a nonzero exit status and @rdlabo/rules/no-implicit-timezone. getDate() reads the host-local day, which bypasses the application timezone. Replace only the added line with:

console.log(toLocalDate(instant));
npx eslint demo.ts
npx tsx demo.ts

Lint should pass again; the added final line prints 2026-01-02.

4. Use it in your app

Follow application setup to choose the default timezone, then enable ESLint in CI. See Timezones and calendar dates for per-user settings, DST, and database boundaries.