CRON DST DRIFT CHECK · RUNS IN YOUR BROWSER

Will your cron job survive daylight saving?

Paste a cron expression and an IANA timezone and see every upcoming run that falls in a spring-forward gap (the local time never happens) or a fall-back overlap (the local time happens twice) — plus a second check for the quieter failure: a scheduler that only understands UTC (GitHub Actions' own schedule: cron included) silently drifting an hour twice a year against the local time you actually meant.

Nothing is uploaded. Every computation runs in this browser using the Intl timezone database your browser already ships.

1. Check a schedule for DST-skip / DST-overlap risk

2. Check a fixed-UTC-only scheduler for drift

For a scheduler with no timezone field — a plain crontab on a UTC host, or GitHub Actions' schedule: cron, which its own docs say always runs in UTC — a single expression cannot hold a local wall-clock time steady across a DST-observing zone. This shows what UTC time you actually need per segment of the year, and the drift between them.

Prefer a CLI, or want this in CI before a deploy?

Same logic, zero dependencies, one file:

node cli.mjs next "30 2 * * *" --tz America/New_York
node cli.mjs next "30 2 * * *" --tz America/New_York --count 5 --from 2027-03-13T00:00:00Z --json
node cli.mjs drift 09:00 --tz America/New_York
node cli.mjs drift 09:00 --tz America/New_York --year 2027 --json

Get cli.mjs — Node 18+, nothing to install, no network call ever. Both subcommands exit 1 when they find DST risk, so either works as a one-line CI check before a new scheduled job ships.

What's checked

CheckHow
Spring-forward skipA cron occurrence's local wall-clock time (e.g. 02:30) does not exist on that calendar date in the chosen timezone, because clocks jumped forward past it
Fall-back overlapA cron occurrence's local wall-clock time occurs twice on that calendar date, because clocks were set back through it — both real UTC instants are reported
Fixed-UTC-cron driftA target local time is converted to UTC once per DST segment of the year; more than one distinct UTC clock time means a single fixed-UTC schedule cannot hold the local time steady

Month and day-of-week accept the standard 3-letter names (JAN–DEC, SUN–SAT), case-insensitive, anywhere a number is allowed — singly, in a list, or as a range (MON-FRI). Minute, hour, and day-of-month stay numeric. Day-of-month and day-of-week follow the standard cron rule: when both are restricted (neither is *), a date matches either one, not both — the single most common cron misreading. See why this happens, and this checker's own named limits, or how this compares to just checking a DST calendar by hand.

Common questions

Why does a cron job skip or double-fire around daylight saving?

A cron expression that names a wall-clock time (like 02:30) in a timezone that observes DST is naming a local time that, twice a year, either does not exist (spring forward: clocks jump from 02:00 straight to 03:00, so 02:30 never happens that day) or happens twice (fall back: 01:00-01:59 occurs twice). Cron implementations do not agree on what to do then — some skip the run entirely, some fire once, some fire twice — so this tool reports the ambiguity rather than guessing which scheduler you run.

Why does a schedule drift an hour twice a year even without a skip or double-fire?

Many schedulers — GitHub Actions' own schedule: cron among them, by its own documentation — always interpret the expression in UTC, with no timezone field at all. A single UTC cron expression cannot hit the same local wall-clock time year-round in any zone that observes DST: it is exactly right for half the year and off by the DST offset, almost always one hour, for the other half. That is not a skip or a double-fire, just a job that quietly runs an hour early or late for months at a time.

Does this tool know what my actual cron daemon or scheduler will do?

No, and it does not claim to. Different cron implementations genuinely disagree on spring-forward and fall-back behavior. This tool computes the two facts that are true regardless of implementation — whether a named local time exists uniquely, doesn't exist, or exists twice on a given date — and leaves the scheduler-specific behavior to your own scheduler's documentation.

Is anything uploaded?

No. Everything is computed in your browser using the standard Intl timezone database your browser already ships, and nothing you type is sent anywhere. The CLI makes no network call either — it is pure Intl/Date arithmetic.