Translate cron to plain English
Paste a cron expression to see what it means, when it next runs in your timezone, and which of cron's several counter-intuitive rules it trips over.
0 9 * * 1-5
At 09:00, Monday through Friday
Interpreted in UTC · approximately 21.6 runs per month
Things to check
Note
Interpreted in UTC
A cron expression has no timezone of its own — the scheduler's zone decides when it fires. These times are computed in UTC. The same expression on a host in another zone runs at a different moment.
Fix: Set the schedule timezone explicitly (TZ= or CRON_TZ= in crontab, `timeZone` in Kubernetes, or the scheduler's own setting). Vercel Cron Jobs always run in UTC.
Fields
- Minute
0 - At minute 0.
- Hour
9 - At 09:00.
- Day of month
* - Every day of the month.
- Month
* - Every month.
- Day of week
1-5 - On Monday, Tuesday, Wednesday, Thursday and Friday.
Next runs
- Thu, 2026-09-03, 09:00
- Fri, 2026-09-04, 09:00
- Mon, 2026-09-07, 09:00
- Tue, 2026-09-08, 09:00
- Wed, 2026-09-09, 09:00
Common schedules
* * * * *every minute*/2 * * * *every 2 minutes*/5 * * * *every 5 minutes*/10 * * * *every 10 minutes*/15 * * * *every 15 minutes*/20 * * * *every 20 minutes*/30 * * * *every 30 minutes*/45 * * * *every 45 minutes0 * * * *every hour0 */2 * * *every 2 hours0 */3 * * *every 3 hours0 */4 * * *every 4 hours0 */6 * * *every 6 hours0 */8 * * *every 8 hours0 */12 * * *every 12 hours0 */5 * * *every 5 hours0 0 * * *every day at midnight0 12 * * *every day at noon0 9 * * *every day at 9am0 6 * * *every day at 6am0 17 * * *every day at 5pm0 23 * * *every day at 11pm0 0,12 * * *twice a day0 9 * * 1-5every weekday at 9am0 0 * * 1-5every weekday0 9-17 * * 1-5every hour during business hours*/15 9-17 * * 1-5every 15 minutes during business hours0 0 * * 0,6every weekend day0 9 * * 1every Monday at 9am0 17 * * 5every Friday at 5pm0 0 * * 0every Sunday at midnight0 2 * * 6every Saturday at 2am0 0 1 * *the first of every month0 0 15 * *the 15th of every month0 0 28-31 * *the last day of the month0 0 1 1,4,7,10 *every quarter0 0 1 1 *once a year on January 10 9 1-7 * 1the first Monday of the month
Built for agents too
The same engine behind this page is available as a JSON API and an MCP server, so an agent can call it directly instead of guessing at cron semantics.
curl 'https://crontoenglish.com/api/v1/explain?expression=0%209%20*%20*%201-5'Questions people actually ask
What do the five fields in a cron expression mean?
In order: minute (0-59), hour (0-23), day of month (1-31), month (1-12), and day of week (0-7, where both 0 and 7 mean Sunday). An asterisk means "every value". So "0 9 * * 1-5" is minute 0, hour 9, any day of the month, any month, Monday through Friday — 09:00 on weekdays.
Why does my "first Monday of the month" schedule run every Monday?
Because standard cron combines day-of-month and day-of-week with OR, not AND. When both fields are restricted, the job runs if EITHER matches. "0 9 1-7 * 1" therefore fires on the 1st through 7th of every month AND on every Monday. To get only the first Monday, leave one field as * and guard the job itself — for example schedule "0 9 1-7 * *" and start the script with [ "$(date +%u)" = "1" ] || exit 0.
What timezone does a cron expression use?
None of its own. A cron expression is just numbers; the scheduler decides which timezone to interpret them in. Traditional crontab uses the system timezone and honours a TZ or CRON_TZ variable. Kubernetes CronJobs take a timeZone field. Vercel Cron Jobs and GitHub Actions always run in UTC. If a schedule has to fire at a specific local time, set the timezone explicitly or convert to UTC yourself.
Does */7 really run every 7 minutes?
Not consistently. A step restarts at the beginning of each field range, and 7 does not divide 60. "*/7 * * * *" fires at minutes 0, 7, 14, 21, 28, 35, 42, 49, and 56, then again at minute 0 of the next hour — an 11-minute gap. Only steps that divide their field evenly (2, 3, 4, 5, 6, 10, 12, 15, 20, 30 for minutes) give a truly regular interval.
How do I run a job on the last day of the month?
Standard cron cannot express it. Quartz-based schedulers have an L specifier, but crontab, Kubernetes, GitHub Actions, and Vercel do not support it. The portable approach is to run daily and exit early unless tomorrow is the 1st: schedule "0 0 * * *" and begin the job with [ "$(date -d tomorrow +%d)" = "01" ] || exit 0. Scheduling "0 0 28-31 * *" instead will fire up to four times a month, not once.
Are @daily, @hourly, and @weekly safe to use?
They are convenient but not portable. These macros come from Vixie cron and are understood by traditional crontab, but many hosted schedulers — including Vercel Cron Jobs, Kubernetes CronJobs, and GitHub Actions — reject them and require five explicit fields. @daily is "0 0 * * *", @hourly is "0 * * * *", @weekly is "0 0 * * 0", @monthly is "0 0 1 * *", and @yearly is "0 0 1 1 *". Using the expanded form always works.
What do L, W, #, and ? mean in a cron expression?
They are Quartz extensions, not standard cron. L means "last" (last day of the month, or last given weekday), W means "nearest weekday", # selects the nth weekday of the month (6#3 is the third Friday), and ? is a placeholder meaning "no specific value". Java Quartz and Spring support them; Unix crontab, Kubernetes, GitHub Actions, and Vercel do not. This tool detects them and reports that it cannot evaluate them rather than guessing at run times you would not actually get.
What is the shortest interval standard cron supports?
One minute. The finest field is minutes, so "* * * * *" — 1,440 runs a day — is the maximum frequency. Six-field expressions that add seconds at the front exist in Quartz and some libraries such as node-cron, but standard crontab rejects them. For sub-minute work, run a long-lived process with its own timer instead of a cron schedule.
Can an AI agent call this tool directly?
Yes, and it is built for that. There is a JSON API at /api/v1/, an MCP server at /api/mcp with explain_cron, next_cron_runs, and build_cron tools, an OpenAPI document at /.well-known/openapi.json, and a machine-readable index at /llms.txt. Every page is also available as markdown at the same URL with an Accept: text/markdown header. The free allowance is 250 calls per day per caller; past that endpoints return HTTP 402 with x402 payment requirements.