Errors that never blame you
When something doesn't fit standard cron, it explains why and suggests a phrasing that works, instead of emitting a wrong expression.
cron-naturally turns plain English into cron and cron back into plain English. Type a schedule, paste an expression, or click an example. Every description it writes parses back to the same cron.
These are the canonical phrases the parser teaches. The grammar it teaches is the grammar it parses, enforced by round-trip tests so the chips never drift from behavior.
Most cron libraries go one direction and stop. This one does both, and handles the messy middle.
When something doesn't fit standard cron, it explains why and suggests a phrasing that works, instead of emitting a wrong expression.
Ambiguous input gets a sane default and surfaces it, returning a ready-made alternative phrasing your UI can offer as a one-click fix.
The set of phrases it teaches is the set it parses. Every English description round-trips back to a semantically identical cron, proven in tests.
Ships ESM with declarations. Runs in the browser and in Node 20+ (this page's demo is the library, bundled and running client-side). One runtime dependency (cron-parser, used only by getNextRuns).
English (or a pasted cron) → a result with the cron, canonical description, and any surfaced assumptions. On failure: a warm hint and up to two suggestions.
Cron → canonical English, or null when outside the supported grammar. Guaranteed to round-trip.
Cron → per-field breakdown for an explain-mode table. The five cells in the translator above are this function.
The next run times in any IANA timezone. The list under the translator is your own timezone, computed live.
import { parseNaturalSchedule, describeCron } from "cron-naturally";
// English → cron
const r = parseNaturalSchedule("every 15 minutes on weekdays");
if (r.ok) {
r.cron; // "*/15 * * * 1-5"
r.description; // "Every 15 minutes on weekdays"
} else {
r.hint; // warm, specific guidance
r.suggestions; // up to two phrasings to try
}
// cron → English
describeCron("0 9 1 * *"); // "Monthly on the 1st at 9:00 AM"