If you've ever stared at a string like 0 9 * * 1-5 and had no idea what it means, you're not alone. Cron expressions look cryptic at first — but once you understand the pattern, you can read and write them in seconds.
This guide breaks down every field, every special character, and gives you 15 real-world examples you can copy straight into your projects. And if you want an instant answer right now, paste any expression into CronRead.com — it translates cron expressions into plain English in real time.
What Is a Cron Expression?
A cron expression is a short string of text that tells a computer when to run a scheduled task. It defines a recurring time schedule — like "every day at midnight" or "every 15 minutes on weekdays."
The name comes from cron, the Unix-based job scheduler that's been around since the 1970s. Today, cron syntax is used everywhere: Linux servers, AWS Lambda, GitHub Actions, Kubernetes, Node.js schedulers, and dozens of frameworks.
A standard cron expression looks like this:
┌──────────── minute (0–59)
│ ┌────────── hour (0–23)
│ │ ┌──────── day of month (1–31)
│ │ │ ┌────── month (1–12)
│ │ │ │ ┌──── day of week (0–7, 0&7=Sunday)
│ │ │ │ │
* * * * *
Five fields, separated by spaces. That's the whole structure.
Anatomy of a Cron Expression: Field by Field
| Position | Field | Allowed Values |
|---|---|---|
| 1 | Minute | 0–59 |
| 2 | Hour | 0–23 |
| 3 | Day of Month | 1–31 |
| 4 | Month | 1–12 (or JAN–DEC) |
| 5 | Day of Week | 0–7 (0 and 7 = Sunday, or SUN–SAT) |
Each field answers one question: when, within this unit of time, should the job run? A * in any field means "every possible value" — so * * * * * means "run every minute of every day."
Special Characters Explained
This is where most people get stuck. Cron uses five special characters to express more complex schedules:
* — Every value
The wildcard. Matches all values for this field.
* * * * * → every minute
0 * * * * → once per hour, on the hour
, — List of values
Lets you specify multiple discrete values in a single field.
0 9,17 * * * → 9:00 AM and 5:00 PM every day
0 0 1,15 * * → midnight on the 1st and 15th of each month
- — Range of values
Defines a continuous range between two values.
0 9-17 * * * → every hour from 9 AM to 5 PM
0 0 * * 1-5 → midnight, Monday through Friday
/ — Step / increment
Means "every Nth value." Used with * or a range.
*/15 * * * * → every 15 minutes
0 */2 * * * → every 2 hours
0 0 1-31/2 * * → every other day, starting the 1st
? — No specific value (Quartz / extended format only)
Used in day-of-month or day-of-week when you only want to specify one of the two. In Quartz Scheduler (common in Java environments), ? signals "I don't care about this field."
0 0 15 * ? → midnight on the 15th (any day of week)
15 Real-World Cron Expression Examples
Use these as-is or adapt them to your needs. Paste into CronRead.com to verify run times before deploying.
Common Mistakes (And How to Avoid Them)
Most cron bugs come from a small set of recurring errors. Here's what to watch out for:
Both 0 and 7 mean Sunday in standard cron — but some tools only accept 0. Always verify the convention for your platform. CronRead.com shows you exactly which day each number maps to.
*/ when you mean a specific range*/30 means "at :00 and :30." But 1-59/30 means "at :01 and :31." These look similar but behave differently. Make sure your starting point is intentional.
In standard cron, if you set both fields (not *), the job runs when either condition is met — not both. This catches a lot of people off guard.
0 0 1 * 1 → runs midnight on the 1st AND every Monday
→ NOT just Mondays that fall on the 1st
Cron uses 24-hour time. 12 is noon, not midnight. Midnight is 0. Writing 0 12 * * * when you mean midnight is one of the most common production bugs in scheduled jobs.
Cron runs in the server's local time zone by default. If your server is UTC and your users are in EST, a job set for 0 9 * * * fires at 4 AM their time. Be explicit about time zones — especially around daylight saving transitions.
Cron Syntax by Platform
Cron isn't a single universal standard. There are meaningful differences across systems:
Standard Unix/Linux Cron
Five fields. Day-of-week is 0–7 (both 0 and 7 = Sunday). No seconds field. Used in crontab files on Linux and macOS servers.
Quartz Scheduler (Java)
Six fields — adds a seconds field at the start: seconds minutes hours day-of-month month day-of-week. Supports L (last), W (nearest weekday), and # (nth weekday of month). Requires ? when specifying one of day-of-month or day-of-week but not both.
Quartz: 0 0 9 * * MON-FRI → 9:00:00 AM, Mon–Fri
Standard: 0 9 * * 1-5 → same schedule, no seconds
AWS EventBridge / Lambda
Six-field format: minutes hours day-of-month month day-of-week year. Requires ? in either day-of-month or day-of-week. Does not support */ in the year field. Minimum rate is 1 minute.
Kubernetes CronJob
Uses standard five-field Unix cron syntax. Schedules run in the node's time zone unless a timeZone field is set in the spec (supported since Kubernetes 1.27).
GitHub Actions
Standard five-field syntax. All schedules run in UTC. Minimum interval is 5 minutes.
Not sure which format your system uses? CronRead.com detects the format automatically and explains it in plain English.
Quick Reference: Named Shortcuts
Many cron systems support named shortcuts instead of expressions:
| Shortcut | Equivalent | Meaning |
|---|---|---|
| @yearly | 0 0 1 1 * | Once a year, Jan 1st at midnight |
| @monthly | 0 0 1 * * | Once a month, 1st at midnight |
| @weekly | 0 0 * * 0 | Once a week, Sunday at midnight |
| @daily | 0 0 * * * | Once a day at midnight |
| @hourly | 0 * * * * | Once an hour, at the top of the hour |
| @reboot | — | Once, at system startup |
These are supported in standard crontab and many frameworks. Quartz Scheduler does not support them.
Paste Any Cron Expression. Get Plain English.
No login. No setup. See the next 10 run times instantly.
Try CronRead.com// free · no account required
Frequently Asked Questions
What does * * * * * mean?
It runs every minute of every hour of every day — the broadest possible cron schedule. A single asterisk in each position means "match every valid value for this field."
What's the difference between 0 0 * * * and @daily?
They are identical — both run once a day at midnight. @daily is simply a named shortcut alias available in systems that support it. Quartz Scheduler does not support this alias.
Can I run a cron job every second?
Not with standard cron, which only supports minute-level precision. Quartz Scheduler adds a seconds field and supports sub-minute scheduling. For anything under one minute, you generally need a dedicated task queue rather than cron.
How do I run a job on the last day of the month?
Standard cron has no "last day" operator. A common workaround is 0 0 28-31 * * paired with a script that checks the date. Quartz Scheduler supports this natively with the L character: 0 0 L * ?.
Why is my cron job not running?
The most common causes are: wrong time zone on the server, an off-by-one error in the hour field (remember, cron uses 24-hour time and midnight is 0), or a typo that creates an invalid expression. Paste your expression into CronRead.com to validate it and see the next scheduled run times before deploying.
What's the difference between standard cron and Quartz cron?
Quartz adds a seconds field at the beginning (making it 6 fields), and introduces special characters like L, W, and #. It also requires ? instead of * in one of the day fields when the other is specified. Standard Unix cron has 5 fields and doesn't support these characters.