cronkit.org
Cron expressions, explained and converted — in your browser

Cron tools › Explain / Test

Cron validator

13 dialects · first error · meaning per dialect · run-by-run comparison

Is this cron expression valid — and does it mean the same thing everywhere it is valid? The validator parses one expression as 13 schedulers would, shows the first error or the plain-English meaning for each, and flags the dialects where the same text runs at different times.

Per dialect

Next 20 runs, by reading

Try one

How to validate a cron expression

  1. Paste the expression exactly as it appears in your config — five fields, six with seconds, an AWS cron(…) or an @ shortcut.
  2. Read the verdict: how many of the 13 dialects accept it, and how many different schedules those acceptances add up to.
  3. Find your scheduler's row. An invalid row shows the first error; a valid row shows what it means there, with the dialect's warnings.
  4. Look for means something different here. It marks dialects whose next runs differ from the Unix cron reading (or, if Unix cron rejects the text, from the first dialect that accepts it).
  5. Where Unix cron accepts the expression, a row can offer a version written for that dialect with the same runs. Copy it, then check the table of next runs.

Three differences that change the meaning

Day-of-month and day-of-week together. When both are restricted, Vixie cron, Kubernetes and Google Cloud Scheduler run on days that match either; Jenkins, Spring, Azure, Celery and node-cron require both; Quartz and AWS require one of them to be ?; Vercel requires one to be *. GitHub Actions and Cloudflare do not document the rule.

What counts as unrestricted. Vixie cron looks at the first character: a field that starts with * counts as unrestricted, so 0 0 */2 * 1 means "odd-numbered days that are Mondays". Kubernetes only treats a bare * or ? that way, so the same string there means "every odd-numbered day, and every Monday".

Day-of-week numbers. Quartz, AWS and Cloudflare Workers number the week 1 = Sunday … 7 = Saturday, so 1-5 from a Linux crontab is Sunday to Thursday there. Linux cron, Spring, node-cron, Jenkins and Cloud Scheduler accept 0-7 with both 0 and 7 meaning Sunday; Kubernetes, Azure and Celery accept only 0-6.

What each dialect accepts

DialectFieldsDay of weekExtras and limits
Unix cron (Vixie, cronie)50-7, SUN-SAT@reboot and the other @ shortcuts; no L W #
GitHub Actions50-6, SUN-SATNo @ shortcuts; shortest interval 5 minutes
Kubernetes CronJob50-6 (7 rejected)? = *; shortcuts except @reboot; no L W #
Jenkins50-7, digits onlyH hashed values; @ aliases expand through H
Quartz6 or 7 (seconds first, optional year)1-7 = SUN-SATExactly one day field must be ?; L W # LW nL
AWS EventBridge6 in cron(…), year last1-7, SUN-SAT? required in one day field; L W #; no / in day of week
Spring @Scheduled6 (seconds first)0-7, MON-SUN? = *; L W #; @ shortcuts
Azure Functions (NCRONTAB)6 (5 also supported)0-6No ? L W #
node-cron5 or 6 (seconds first)0-7? L W #; shortcuts except @reboot
Celery crontab.from_string()50-6 (7 raises)Day fields AND
Google Cloud Scheduler50-6, SUN-SAT or 7No L
Vercel50-6, no namesOne day field must be *; always UTC
Cloudflare Workers51-7 (1 = Sunday)L W #; UTC

To convert between two of them with the day numbers and ? handled for you, use cron to Quartz or Quartz to cron; to see two schedules side by side run by run, use the cron diff.

FAQ

Why is my Linux cron expression invalid in Quartz and AWS?

Two reasons, usually both. Quartz starts with a seconds field and AWS ends with a year field, so five fields are the wrong count. And both need ? in either day-of-month or day-of-week, because they do not support restricting both. Fixing only those is not enough when the day of week has numbers: their week starts at 1 = Sunday.

What does "means something different here" compare?

The next 100 run times in UTC, computed with each dialect's own rules, against the Unix cron reading. Dialects with identical runs share a letter (A, B, …); a row with a different letter runs at other times. The table under the dialects shows the first 20 runs of each reading and highlights the ones the first reading does not have.

Why are GitHub Actions and Cloudflare marked with a warning when both day fields are set?

Neither documents whether day-of-month and day-of-week combine with AND or OR. The validator shows one plausible reading, but the safe choice is to keep one of the two fields *.

How does the Jenkins row handle H?

H is replaced by a value hashed from the job's full name, so the same spec runs at different minutes for different jobs. Type the job name in the box to see the times Jenkins would pick for it; the other dialects reject H.