Time & Scheduling

Cron Explainer

Paste a cron expression to read it in plain English, check every field, and see exactly when it will next run in your time zone, including the day-of-month / day-of-week OR rule and DST shifts. Evaluated in your browser.

Five fields (minute hour day-of-month month day-of-week), six with seconds first, or a macro such as @daily.

Cron explainer options

Keyboard shortcuts

Esc
Close a menu or overlay, then leave full screen
↓ on a menu
Open it; ↑ ↓ move through its items
← → in the menu bar
Move between menus

Where your data goes

Using this page Using the API, MCP or A2A
Where it runs In your browser. Parsing, the English description and the run-time calculation run in the page with cron-parser, cronstrue and Luxon, using your browser's time-zone data. Nothing is sent anywhere. In a Cloudflare Pages Function at the Cloudflare data centre nearest the caller.
What leaves your device Nothing you enter. After the page and its scripts load, no request carries your input. The browser enforces this: the page's Content-Security-Policy sets connect-src 'none' and form-action 'none', which block fetch, XHR, WebSocket, EventSource, beacons and form posts.

The server receives the cron expression, zone and start time, evaluates them in memory, and returns the result. Your input is not stored or logged; only the per-call metadata row (operation, time, status, sizes) is recorded.

Stored Nothing leaves the page. No cookies, analytics or third-party scripts; the browser keeps only your View → Inline config choice. Your inputs and results: never. What is stored is your client record (client ID, a SHA-256 hash of your secret, expiry, and the profile you registered with) and one metadata row per call: operation, time, transport, status, error code, duration, request and response sizes, and country.
Logged Nothing (no requests are made). Only the per-call metadata above, attributed to your client ID. Never parameters, bodies, results, or credentials. Cloudflare, as the host, also processes request metadata (IP address, full URL including the query string, headers) under its own policies, so put inputs in POST bodies.
Access Open to anyone. Requires a client ID and secret (how to get one). HTTPS only; TLS terminates at Cloudflare.

Details and how to verify this yourself: Security & privacy.

User guide

The tool sits in a window that works like a desktop app: menus on the top row and the full-screen icon at its right (Esc leaves full screen). The set-up options described below are in Settings → Options…, an overlay, and the Settings menu also lists the common choices directly. To keep the options in view instead, choose View → Inline config; the page remembers that choice. Help → Keyboard shortcuts… lists the keys.

  1. Type a cron expression, for example */15 9-17 * * 1-5.
  2. Choose the time zone your cron daemon or scheduler runs in. It defaults to your browser’s zone. Servers often run in UTC. Kubernetes CronJobs use the controller’s zone unless spec.timeZone is set.
  3. Read:
    • the description in plain English;
    • the day rule: which of the two day fields decides, and whether they combine with OR or AND;
    • the fields table, with every value each field expands to;
    • the next runs, with the UTC equivalent of each. Runs moved by a DST change are marked.

The rule that surprises everyone. When both day-of-month and day-of-week are restricted, cron runs on days matching either of them. 0 0 13 * 5 runs at midnight on every 13th and on every Friday, not only on Friday the 13th. To run on a weekday within a range of days, schedule on the weekday and check the date in the job, e.g. [ "$(date +\%d)" -le 07 ] for “first Monday”.

Syntax at a glance.

SyntaxMeaningExample
*every value* * * * * every minute
a,blist0 9,17 * * * at 09:00 and 17:00
a-brange (inclusive)0 9-17 * * * every hour 09:00 to 17:00
*/n, a-b/nstep*/10 * * * * every 10 minutes
namesJAN–DEC, SUN–SAT, any case0 0 * * MON-FRI

Specification

Accepted forms.

FormFields
Standard (Vixie cron, cronie, Kubernetes)minute hour day-of-month month day-of-week
With seconds (cron-parser, node-cron, Spring style)second minute hour day-of-month month day-of-week; a warning notes that standard crontab does not accept it
Macros (case-insensitive)@yearly = @annually = 0 0 1 1 *; @monthly = 0 0 1 * *; @weekly = 0 0 * * 0; @daily = @midnight = 0 0 * * *; @hourly = 0 * * * *

Fields are separated by any whitespace. Any other number of fields is rejected; a 7th (Quartz “year”) field is named in the error.

Field values.

  • Ranges: second and minute 0–59, hour 0–23, day-of-month 1–31, month 1–12, day-of-week 0–7.
  • Sunday is both 0 and 7; the values list always reports Sunday as 0.
  • Steps: a step of 0, or a range written backwards (5-1), is an error.

Extensions. These are accepted, and each use produces a portability warning, because Vixie cron and cronie reject them:

SyntaxFieldMeaning
Lday-of-monthlast day of the month (L, or in a list: 1,L)
nLday-of-weeklast weekday n of the month (5L = last Friday)
n#kday-of-weekk-th weekday n of the month, k = 1–5 (1#2 = second Monday); cannot be combined with a list
?day fieldssame as *

Rejected, with an explanation.

  • H (Jenkins hash), W and LW (nearest weekday);
  • @reboot (it has no schedule), and the non-standard macros @weekdays, @weekends, @minutely and @secondly;
  • any value outside the field’s range.

Every syntax and range error starts with the name of the offending field, e.g. minute field "61": ….

Day-of-month and day-of-week (Vixie cron rule).

  • Unrestricted field: a day field is unrestricted when it begins with * (this includes */2) or is ?.
  • Both restricted (0 0 13 * 5): a day matches when either field matches. day_rule.rule is either.
  • One field * or ?: only the other field selects days (day-of-month or day-of-week). If both are, every day matches (every-day).
  • A *-prefixed field that still narrows (0 0 */2 * 1): Vixie cron counts it as unrestricted, so a day must match both fields (an odd day that is also a Monday). day_rule.rule is both. This matches Vixie cron’s DOM_STAR/DOW_STAR flags and robfig/cron (Kubernetes). cron-parser alone would OR these fields; this tool filters its results to apply the Vixie rule.

Run times.

  • Search: runs are listed strictly after from (default: now), in ascending order, at whole-second resolution.
  • count: 1–50 (default 5 on the API, 10 on the page).
  • Zone: run times are computed in zone with cron-parser, then shown as ISO 8601 with offset, UTC, Unix seconds, wall-clock time and weekday.
  • Never-matching days: a schedule whose day fields can never match (0 0 30 2 *) is rejected by cron-parser with a 422 error.
  • Rare schedules: if the search ends before count runs are found, the list is shorter and warnings says why. cron-parser stops at its internal loop limit, and the AND filter examines at most 5,000 candidates.

Daylight saving time. Behaviour in a zone with DST, verified for America/New_York:

  • Spring forward (gap). A run scheduled at a wall-clock time that does not exist is moved forward by the gap. 30 2 * * * runs at 03:30 EDT on the changeover day and is flagged dst_shifted: true. Runs every 20 minutes during 02:00–02:59 run at 03:00, 03:20 and 03:40.
  • Fall back (overlap). A job at a fixed time in the repeated hour runs once, at the first occurrence: 30 1 * * * runs at 01:30 EDT, not again at 01:30 EST. A job whose hour field is * runs in both copies of the hour (30 * * * * runs at 01:30 EDT and 01:30 EST).

Real daemons differ in this. cronie runs skipped jobs immediately after the change; some systems skip them. Check your scheduler if it matters, or run the job in UTC.

Description. The English text comes from cronstrue (24-hour clock). For expressions where both day fields are set, its wording (“on day 13 of the month, and on Friday”) is less precise than day_rule.explanation, which is authoritative.

Limits. Expression up to 200 characters.

API & MCP

The same logic is available over HTTP and as MCP tools. Unlike this page, these run on the server: see where your data goes.