Cron Expression Tester

Enter a standard 5-field cron expression (minute hour day-of-month month day-of-week) and see a human-readable description, the next 10 execution times, and an estimate of executions per month. All parsing and scheduling runs in your browser.

Quick presets:

🟢📖 Cron Expression Syntax

A cron expression is a string of 5 fields separated by spaces. This tool uses the standard Vixie cron format (used by cronie, vixie-cron, and most Linux distributions).

*Matches every value. * * * * * = every minute.
5Matches exactly 5. 0 5 * * * = 5:00 AM daily.
,List separator. 0,30 * * * * = at 0 and 30 minutes past each hour.
-Range. 9-17 * * * 1-5 = hours 9 through 17, Monday through Friday.
/Step. */15 * * * * = every 15 minutes. Equivalent to 0,15,30,45.

Day-of-week numbering: 0=Sunday, 1=Monday, ..., 6=Saturday. Some cron implementations use 7 for Sunday. This tool accepts both.

Day-of-month vs. day-of-week: When both are specified (not *), the cron job runs when either condition is met. For example, 0 0 1 * 1 runs at midnight on the 1st of the month and every Monday.

Common pitfalls: 1) Using 0 for month (months start at 1, not 0). 2) Forgetting that */N starts from the minimum value, not from current time —*/15 in minutes means 0, 15, 30, 45. 3) Assuming 7-field cron (with seconds and year) — this tool uses the standard 5-field format.

🕐 Daylight saving: cron reads the wall clock

Cron schedules against the system's local wall clock rather than against elapsed time. Twice a year that distinction produces a discrepancy nobody notices until a job is missing from the results.

In spring, when 02:00 jumps directly to 03:00, anything scheduled inside that hour is skipped for the day — 30 2 * * * does not run on the switchover date. In autumn, when 02:00 occurs twice, the same job runs twice.

What to do depends on the job. A nightly aggregation can simply move outside the transition hour: 0 4 * * * is safe in every timezone that shifts by one hour at 02:00. A job that must run exactly once per calendar day regardless of clock changes should be scheduled in UTC — set CRON_TZ=UTC at the top of the crontab where the implementation supports it, and convert inside the job.

🧩 Why it works when you type it and fails in cron

Cron starts jobs with a minimal environment: no login shell, no ~/.bashrc, and a PATH that is usually just /usr/bin:/bin. Four consequences account for almost every "it runs fine from the terminal" report.

  • Command not found. A binary in /usr/local/bin, or anything managed by a version manager, is not on cron's PATH. Use the absolute path in the crontab rather than exporting PATH and hoping it propagates.
  • Environment variables are gone. API keys, virtualenv activation, NODE_ENV — none of it exists. Define what the job needs at the top of the crontab, or source a file from inside the script.
  • Output goes to email. A job that fails silently is usually mailing its error somewhere nobody reads. Redirect both streams explicitly: >> /var/log/job.log 2>&1. Without that, failures vanish.
  • Percent signs are special. In a crontab, % is interpreted as a newline and everything after it becomes the job's standard input. A date like date +%Y-%m-%d has to be written date +\%Y-\%m-\%d. This single rule has broken more log-rotation scripts than any other.

🔁 Overlap, and counting runs before you commit

Cron has no concept of a job that is still running. Let a backup take 90 minutes while the schedule fires hourly and you get two processes competing for the same files, then three. The standard guard is a lock — wrap the command so an overlapping run exits instead of stacking: flock -n /var/lock/backup.lock /usr/local/bin/backup.sh.

It is worth multiplying a schedule out before deploying it. Take */15 9-17 * * 1-5: four firings per hour, nine hours in the window, about 21.7 weekdays in an average month. That lands at 4 × 9 × 21.7 ≈ 782 runs per month, or roughly 9,400 a year. If a run costs a few cents of API calls or occupies a worker for a minute, that arithmetic — not the code — decides the bill. The run-count panel above does the multiplication for you.

If an expression is hard to read, treat that as a signal. 0 3 * * 0 and 0 3 * * 7 both mean Sunday at 03:00 in most implementations, which is exactly the kind of ambiguity a named macro avoids: @daily, @weekly, @reboot all work in Vixie cron. For anything needing retries, dependencies, or logging by default, a systemd timer is the better tool — cron's advantage is that it exists everywhere and asks you to learn nothing.

See also: Cron Execution Frequency Per Month · Unix Timestamp Converter · Chmod Calculator