Introduction to Cron
Cron is a time-based job scheduler in Unix-like operating systems that runs commands or scripts automatically at specified times. Cron expressions are the language used to define when and how often jobs should run.
Cron expressions look cryptic at first—a string of numbers and special characters that seem almost incomprehensible. However, once you understand the structure and syntax, reading and writing cron expressions becomes straightforward.
Cron Expression Structure
A cron expression consists of five fields separated by spaces, each representing a different unit of time:
┌───────────── minute (0 - 59)
│ ┌───────────── hour (0 - 23)
│ │ ┌───────────── day of month (1 - 31)
│ │ │ ┌───────────── month (1 - 12)
│ │ │ │ ┌───────────── day of week (0 - 7) (0 or 7 is Sunday)
│ │ │ │ │
│ │ │ │ │
* * * * *
Each field specifies when the job should run:
- Minute (0-59): Which minute within the hour
- Hour (0-23): Which hour within the day (24-hour format)
- Day of Month (1-31): Which day of the month
- Month (1-12): Which month
- Day of Week (0-7): Which day of the week (0 and 7 both represent Sunday)
Reading Cron Expressions
Let's look at some common examples to understand how to read cron expressions:
Example 1: Daily at Midnight
0 0 * * *
- Minute: 0 (top of the hour)
- Hour: 0 (midnight)
- Day of Month: * (every day)
- Month: * (every month)
- Day of Week: * (every day of the week)
This runs at 00:00 (midnight) every day.
Example 2: Every Hour
0 * * * *
- Minute: 0 (top of the hour)
- Hour: * (every hour)
- Day of Month: * (every day)
- Month: * (every month)
- Day of Week: * (every day of the week)
This runs at the top of every hour (1:00 AM, 2:00 AM, etc.).
Example 3: Every 30 Minutes
*/30 * * * *
- Minute: */30 (every 30 minutes)
- Hour: * (every hour)
- Day of Month: * (every day)
- Month: * (every month)
- Day of Week: * (every day of the week)
This runs at minutes 0 and 30 of every hour.
Example 4: Weekdays at 9 AM
0 9 * * 1-5
- Minute: 0 (top of the hour)
- Hour: 9 (9 AM)
- Day of Month: * (every day)
- Month: * (every month)
- Day of Week: 1-5 (Monday through Friday)
This runs Monday through Friday at 9:00 AM.
Example 5: First Day of Month at 2 AM
0 2 1 * *
- Minute: 0 (top of the hour)
- Hour: 2 (2 AM)
- Day of Month: 1 (first day)
- Month: * (every month)
- Day of Week: * (every day of the week)
This runs on the first day of every month at 2:00 AM.
Cron Expression Syntax
Asterisk (*)
An asterisk means "every" value for that field.
* * * * * // Every minute of every hour of every day
0 * * * * // Every hour
0 0 * * * // Every day at midnight
Numbers
Specific numbers select specific times:
30 14 * * * // 2:30 PM every day
0 9 15 * * // 9 AM on the 15th of every month
0 0 * 12 * // Midnight every day in December
Comma (,)
Commas list multiple values:
0 9,12,15 * * * // 9 AM, 12 PM, and 3 PM every day
0 0 1,15 * * // Midnight on the 1st and 15th of every month
0 0 * * 0,6 // Midnight on Saturday and Sunday
Range (-)
Dashes specify a range of values:
0 9-17 * * * // Every hour from 9 AM to 5 PM
0 0 1-7 * * // Midnight on the 1st through 7th of every month
0 0 * * 1-5 // Midnight Monday through Friday
Slash (/)
Slashes specify intervals (step values):
*/15 * * * * // Every 15 minutes
0 */2 * * * // Every 2 hours
0 0 * * */2 // Every other day
*/5 9-17 * * * // Every 5 minutes from 9 AM to 5 PM
The slash is often used with asterisks to mean "every N values," but you can also use ranges:
0 0-5/1 * * * // Every hour from midnight to 5 AM (0, 1, 2, 3, 4, 5)
0 0-23/6 * * * // Every 6 hours (0, 6, 12, 18)
Question Mark (?)
A question mark is allowed in day of month or day of week fields to mean "no specific value." This is useful when you want to specify one field but not the other:
0 0 1 * ? // 1st of every month (day of week doesn't matter)
0 0 ? * 1 // Every Monday (day of month doesn't matter)
The question mark helps avoid conflicts when specifying either day of month or day of week.
Month and Day of Week Names
Many cron implementations support names instead of numbers for months and days of week:
Months: JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC
Days: SUN, MON, TUE, WED, THU, FRI, SAT
0 0 1 JAN * // January 1st at midnight
0 9 * * MON-FRI // Weekdays at 9 AM
0 0 15 * FRI // 3 PM on Friday the 15th
Complex Cron Expressions
Let's look at more complex examples:
Business Hours
0 9-17 * * 1-5
Every hour from 9 AM to 5 PM on weekdays.
Twice Daily
0 6,18 * * *
At 6 AM and 6 PM every day.
Quarterly
0 0 1 1,4,7,10 *
At midnight on the first day of January, April, July, and October.
Every 3 Hours
0 */3 * * *
At midnight, 3 AM, 6 AM, 9 AM, noon, 3 PM, 6 PM, 9 PM every day.
Every 15 Minutes During Work Hours
*/15 9-17 * * 1-5
Every 15 minutes from 9 AM to 5 PM on weekdays.
Important Considerations
Day of Month vs. Day of Week
When both day of month and day of week are specified (neither is *), the job runs on days matching EITHER condition:
0 0 1 * 5 // Runs on the 1st of every month OR every Friday
To run only when BOTH conditions match, you might need to use a question mark.
Hour and Minute Precision
Cron's minimum granularity is typically one minute. You cannot schedule jobs to run at specific seconds using standard cron syntax.
24-Hour Format
Hours are in 24-hour format (0-23). 13:00 is 1 PM, 20:00 is 8 PM.
Timezone Considerations
Cron typically runs in the system's timezone. Some cron implementations allow specifying timezone, but you should verify how your system handles timezones.
Common Mistakes
- Using 7 for Sunday instead of 0: Many implementations accept both 0 and 7 for Sunday, but be consistent
- Using 1-based indexing for hours/minutes: Hours and minutes are 0-based (0-59 for minutes, 0-23 for hours)
- Forgetting that months are 1-based but day-of-week is usually 0-based: Month 1 is January, but Sunday is 0 (or 7)
- Not accounting for timezone differences: Cron runs on the server's timezone, not the user's timezone
Tools for Validating Cron Expressions
Because cron syntax is terse and easily mistakes, validation tools are useful:
- Online cron validators: Websites like crontab.guru let you enter an expression and see when it will run
- cron-parser libraries: Most programming languages have libraries to validate and test cron expressions
- Testing before deployment: Always test a cron job on a test schedule before deploying to production
Mastering cron syntax is essential for system administrators and developers who need to schedule automated tasks. Once you understand the five fields and the special characters, you can read and write cron expressions confidently. Start with simple expressions (daily at midnight), then build toward more complex schedules as your confidence grows.