Scrawlspace › Developer Utilities
Cron Expression Explainer
Paste a cron expression to read the schedule in plain English, see when it will run next in local time or UTC, and check each field as you type. It follows standard five-field crontab syntax as described in crontab(5), including names such as MON and JAN and shortcuts such as @daily.
How to use Cron Expression Explainer
- Type a Cron expression, e.g. 0 9 * * 1-5, or pick one of the Examples.
- Read the plain-English description of the schedule. A field with a mistake is marked with what's allowed.
- Switch Time zone between Local and UTC, to match the server or platform that will run the job.
- Check the Next runs list to confirm it fires when you expect.
Frequently asked questions
How do I read a cron expression?
Standard cron has five fields: minute, hour, day of month, month and day of week. For example, 30 18 * * 5 means 18:30 every Friday. Paste one here to see it in words.
What do *, comma, - and / mean in cron?
* means every value. A comma makes a list (1,15 is the 1st and 15th). A hyphen makes a range (1-5 is Monday to Friday in the day-of-week field). A slash sets a step: */5 in the minute field runs every five minutes, and 8-18/2 in the hour field runs every two hours from 08:00 to 18:00.
Why does my job run on extra days?
When both day of month and day of week are restricted (neither is *), cron runs when either one matches. 0 0 1 * 1 runs on the 1st of the month and on every Monday, not only on Mondays that are the 1st. The explainer says or when this applies.
Does it support @daily and other shortcuts?
Yes. @hourly, @daily, @midnight, @weekly, @monthly, @yearly, @annually and @reboot are recognised.
Why does my cron expression have six fields?
Standard cron uses five. Spring uses six with seconds first and no year field. Quartz also puts seconds first and allows an optional seventh field for the year. AWS EventBridge uses six fields that end with a year. This tool explains the standard five-field format and points out six-field input.
Does cron run in UTC or local time?
Classic cron uses the server's local time zone. GitHub Actions schedules always run in UTC, AWS EventBridge cron rules use UTC, and a Kubernetes CronJob uses the controller's zone unless you set its timeZone field. Use the UTC switch to check, and the timestamp converter to compare zones.
Cron fields and allowed values
| Field | Allowed values | Example |
|---|---|---|
| Minute | 0–59 | */15: every 15 minutes |
| Hour | 0–23 | 9-17: every hour from 09:00 to 17:00 |
| Day of month | 1–31 | 1: the 1st |
| Month | 1–12 or JAN–DEC | 1,7: January and July |
| Day of week | 0–6 or SUN–SAT (7 is also Sunday) | 1-5: Monday to Friday |
Common schedules
- */15 * * * *: every 15 minutes.
- 0 * * * *: every hour, on the hour.
- 0 9 * * 1-5: 09:00 on weekdays.
- 30 18 * * 5: 18:30 every Friday.
- 0 0 1 * *: midnight on the 1st of every month.
- 0 */6 * * *: every 6 hours, at 00:00, 06:00, 12:00 and 18:00.
- "First Monday of the month" can't be written in standard cron: 0 9 1-7 * 1 runs on days 1 to 7 and on every Monday. Schedule 0 9 1-7 * * and check the weekday in the script instead.
Cron on different platforms
| Platform | Fields | Differences |
|---|---|---|
| Unix cron (Vixie, cronie) | 5 | Server time zone. The day-of-month and day-of-week OR rule. % in the command must be escaped as \%. |
| Kubernetes CronJob | 5 | Standard syntax. Optional timeZone field. |
| GitHub Actions | 5 | Always UTC. Runs can be delayed when load is high. |
| Spring @Scheduled | 6 | Seconds first, no year. Supports ? and L, W and # for days. |
| Quartz | 6 or 7 | Seconds first, optional year last. ? required in one day field; L, W and #. |
| AWS EventBridge | 6 | Minutes first, year last. ? required in one day field. UTC. |
Why didn't my cron job run?
- The server's time zone isn't the one you assumed. Check the next runs in UTC, and convert a run time to other zones with the world clock.
- An unescaped % in the crontab command line, which cron turns into a newline.
- The job's environment: cron runs with a minimal PATH and no login profile, so use full paths.
- A day that doesn't exist: 0 0 31 * * skips every month with fewer than 31 days, and 0 0 30 2 * never runs.
- A step that doesn't divide evenly: */7 in the minute field runs at 0, 7 … 56 and then again at 0, so the gap across the hour is 4 minutes.