Skip to content
Code Recycle

Component · for humans & their agents

Cron Semantics: DST, Catch-Up and Overlap

verified · first-partyactively maintained$0 during beta (was $69)

On the spring-forward day a 02:30 job never runs, and most schedulers skip it silently.

by ringbuffer · Code Recycle admin

Get it free — beta

Every claim on this page is refundable if it is untrue — refund policy.

Verified: 140 tests

Cron parsing and next/previous fire times in a real timezone, with the DST cases handled by an explicit caller-chosen policy.

Cron parsing and next/previous fire times in a real timezone, with the DST cases handled by an explicit caller-chosen policy.

THE SILENT FAILURE. A cron expression looks unambiguous and is not. On the spring-forward day a job scheduled for 02:30 local NEVER RUNS, because that time does not exist, and most schedulers skip it silently -- a daily report is simply missing one day a year. On the fall-back day 01:30 happens TWICE, and a job runs either twice (double-charging, double-emailing) or once, with no way to tell which you got.

Separately, the day-of-month and day-of-week fields have counter-intuitive OR semantics when both are restricted, which POSIX specifies and almost every hand-rolled parser gets wrong -- so a schedule fires far more often than intended and nobody notices, because extra runs look like normal activity. That rule is implemented, cited, and tested.

The DST policy is chosen by the caller -- skip, shift, or run both -- and REPORTED in the result rather than silently defaulted. An expression that can never fire, like February 30th, is reported as unsatisfiable rather than returning null or searching forever. Missed-run detection lists the fire times an outage cost you, because silently resuming as if nothing was missed is how data gaps happen.

A REAL BUG FOUND BEFORE RELEASE: the result reported occurrence 'both' while carrying only ONE instant, contradicting its own type documentation and README. It was reachable through the missed-run API, so a billing job trusting that label would have silently processed one of two real instants -- the exact double-or-missing-run bug this product prevents.

VERIFIED: 140 tests. Every mutation was observed FAILING before the source was restored -- a test never seen to fail is a decoration. Independently reviewed by a verifier whose job was to find what is wrong, not to agree.

DELIVERY: signed download of a hash-verified tarball, immediately on purchase. Permissive licence: unlimited products, unlimited clients, unlimited seats, no attribution, perpetual and irrevocable. One restriction, do not republish the source as source.

Interface

What you call, and what comes back. Types and signatures only — the implementation ships with the source.

  export function isLeapYear(year: number): boolean;
  export function daysInMonth(year: number, month: number): number;
  export function isValidCalendarDate(year: number, month: number, day: number): boolean;
  export function calendarDateFromEpochDay(epochDay: number): CalendarDate;
  export function epochDayFromCalendarDate(year: number, month: number, day: number): number;
  export function parseField(raw: string, range: FieldRange): FieldParseOutcome;
  export function resolveOccurrence( year: number, month: number, day: number, hour: number, minute: number, timeZone: string, policy: DstPolicy, ): ResolvedFire;
  export function narrowOccurrenceToWindow(resolved: ResolvedFire, windowedFireTimes: number[]): Occurrence;
  export function findMissedRuns( schedule: CronSchedule, timeZone: string, lastRunEpochMs: number, nowEpochMs: number, dstPolicy: DstPolicy, options: MissedRunsOptions = {}, ): MissedRunsSearchResult;
  export function parseCronExpression(expression: string): ParseResult;
  export function dayMatches(schedule: CronSchedule, year: number, month: number, day: number, dayOfWeek: number): boolean;
  export function timesOfDay(schedule: CronSchedule): Array<;
  export type FieldParseOutcome = { ok: true;
  export type WallClockResolution = | { kind: "normal";
  export type ParseFieldError = { field: FieldName;
  export type FieldName = "minute" | "hour" | "dayOfMonth" | "month" | "dayOfWeek";
  export type ParseResult = | { ok: true;
  export type DstPolicy = "skip" | "shift" | "both";

01Capabilities

Does

  • + Scheduling

Doesn’t

  • No exclusions declared

02Requirements & stack

Depends on

No declared dependencies

Credentials needed

None declared

Stack

typescript

03Community

No endorsements yet

No verified confirmations yet — be the first.

Confirmations come from verified purchasers, installers, vetted reviewers, or an installation outcome your org reported through the agent tools. They grade quality — security is verified separately, and community votes can never override the security gate.

Open an issue

Sign in to confirm — weight comes from verified usage, not vote count.

0 open · 0 answered · 0 fixed · 1 said it worked

04Trust Passport

Full passport →
–/100

0/0 automated components pass. An automated score is never a security guarantee.

✓ Verified · first-partyreviewed Sep 20, 2026 · re-verification due Dec 19, 2026
  • publisher identity Publisher status verified; 1 verification(s) on file
  • malicious pattern scan No known malicious-behavior patterns across 24 source file(s) plus listing text
  • capability contract All 0 observed capability reference(s) match the declared manifest
  • agent safety scan No injection patterns in agent-readable content
  • provenance No release signature or provenance attestation
  • behavioral sandbox Not performed in this environment — requires the production isolated runner (docs/sandbox-requirements.md). No untrusted code is ever executed on the application host.

Every listing must pass this review before it can be sold, and it is re-run on every release. Verification describes what we checked — it is not a guarantee that the software is safe.

VersionChannelReleasedNotes
1.0.0stableAug 4, 2026First public release.