What a cron expression is
Cron is the Unix service that runs commands on a schedule. Each line of a crontab file starts with five time fields, and the rest of the line is the command. The cron daemon checks the table every minute and runs each command whose fields all match the current time. This cron expression builder reads the five fields the same way, explains them in plain English and lists the next run times, so you can check a schedule before it goes live, or generate a new one without remembering the syntax.
| Field | Allowed values | Example |
|---|---|---|
| Minute | 0 to 59 | 30 at half past |
| Hour | 0 to 23 | 9-17 from 9 AM to 5 PM |
| Day of month | 1 to 31 | 1,15 on the 1st and 15th |
| Month | 1 to 12, JAN to DEC | */3 every third month |
| Day of week | 0 to 7, SUN to SAT | 1-5 Monday to Friday |
POSIX, the standard behind crontab, defines the asterisk for "every value", commas for lists and a hyphen for inclusive ranges, and it numbers the weekdays 0 to 6 starting with Sunday. Cronie, which is based on the original Vixie cron, adds three things: a step with a slash (*/15 or 0-30/10), the first three letters of month and day names in any case, and 7 as a second way to write Sunday. GitHub Actions documents weekdays as 0 to 6 only, so 0 is the safer way to write Sunday. A step only counts within its own field, so */23 in the hour field means midnight and 11 PM, not every 23 hours.
The day of month and day of week rule
This is the rule that surprises people most. A job runs when the minute, hour and month match and at least one of the two day fields matches. If one of the day fields is an asterisk, only the other one matters. If both are restricted, a day that matches either of them counts. So 30 4 1,15 * 5 runs at 4:30 AM on the 1st and 15th of every month and also on every Friday, as the cronie manual itself shows with this example.
Cronie treats a field that starts with an asterisk, like */2, as not restricted, so 0 0 */2 * 1 runs only on odd-numbered days that are Mondays. Other tools do not all agree on this detail, which is another reason to check the run times. If you need "the first Monday of the month", standard cron cannot say it directly; run on days 1 to 7 with the day of week left as an asterisk and let the command check the weekday.
Cron shortcuts
| Shortcut | Same as | Runs |
|---|---|---|
| @yearly, @annually | 0 0 1 1 * | Midnight on January 1 |
| @monthly | 0 0 1 * * | Midnight on the 1st of each month |
| @weekly | 0 0 * * 0 | Midnight every Sunday |
| @daily | 0 0 * * * | Midnight every day |
| @hourly | 0 * * * * | At the start of every hour |
| @reboot | No time fields | Once after the system reboots |
The cronie manual documents these shortcuts; they are not part of POSIX. GitHub Actions does not support any of them, so write the five fields there.
Time zones and daylight saving time
A cron line has no time zone. The daemon matches it against its own clock, so the same line can fire at different moments on a laptop and on a server set to UTC; the time zone converter shows what a UTC time is in your city. Cronie can set a zone for one crontab with a CRON_TZ= line. GitHub Actions runs schedules in UTC unless the workflow adds a timezone key with an IANA name like America/New_York.
Daylight saving time creates two odd cases. In the US, for example, clocks jump from 2 AM to 3 AM on the second Sunday of March, so a job at 2:30 AM has no 2:30 that day. On the first Sunday of November, 2 AM becomes 1 AM again and the hour repeats, so 1:30 AM happens twice. The run list above marks both cases, and the note under it explains what different schedulers do. If a job must run exactly once a day, schedule it outside the hours when your clocks change, or run cron in UTC.
Cron formats that are not crontab
Several tools use the word cron for a different format. Pasting one of them here gives a clear error and, where possible, a button that converts it.
- Quartz has 6 or 7 fields: seconds first, then the usual five, then an optional year. Weekdays run from 1 to 7 with Sunday as 1. One of the two day fields must be ?, and it adds L (last), W (nearest weekday) and # (like 6#3 for the third Friday).
- Spring also puts seconds first, but keeps the cron weekday numbers 0 to 7 with Sunday as 0 or 7. It supports ?, L, W and # as well.
- Amazon EventBridge scheduled rules write cron(0 12 * * ? *): six fields with a year at the end, weekdays 1 to 7 from Sunday, and a required ? in one of the day fields. Its examples are in UTC.
- GitHub Actions uses the standard five fields. The shortest interval is every 5 minutes, and runs can be delayed when load is high, especially at the start of every hour.
Running on the last day of the month
Crontab has no L. One way is to run on the last possible days and let the shell decide. With GNU date, which understands "tomorrow", this runs the script only when tomorrow is the 1st:
0 23 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /path/to/scriptThe backslash before % matters: in a crontab line an unescaped % ends the command and turns the rest into input for it.
How to use the cron expression builder
- 1Type or paste an expression, tap a common schedule, or pick Minutes, Hourly, Daily, Weekly or Monthly under Build a schedule.
- 2Read the plain-English explanation and the notes. Fix any field marked in red; the message says what each field allows.
- 3Check the next 10 run times in your time zone, in UTC or in your server's zone, then copy the expression or a link.
Frequently asked questions
What does */5 * * * * mean?
It runs every 5 minutes: at minute 0, 5, 10 and so on up to 55 of every hour, every day. The */5 in the minute field is a step, which means every fifth value of the whole range. The four asterisks after it mean every hour, every day of the month, every month and every day of the week.
How do I run a cron job every weekday at 9 AM?
Use 0 9 * * 1-5. The 0 is the minute, 9 the hour, and 1-5 in the last field means Monday through Friday, since cron counts Sunday as 0. You can also write MON-FRI, which cronie accepts, though POSIX itself only defines numbers.
Why does my job run on days I did not expect?
Probably because both day fields are set. When the day of the month and the day of the week are both restricted, cron runs on days that match either one. 0 0 1 * 1 runs on the 1st of every month and on every Monday, not only on Mondays that fall on the 1st. The explanation above warns you when this rule applies.
What time zone does cron use?
A crontab line has no time zone of its own. The cron daemon reads the times in its own time zone, so check what your server uses. cronie lets you set a zone for a whole crontab with a CRON_TZ line, and GitHub Actions uses UTC unless you add a timezone key. Switch the next run times above between your time zone, UTC and any other zone to check.
Can cron run a job every 30 seconds?
Not with the standard 5 fields: the smallest unit is one minute. Quartz and Spring add a seconds field at the start, which gives 6 fields. If you paste such an expression here, the builder offers to drop the seconds so you can read the rest as standard cron.
How do I schedule a job on the last day of the month?
Standard cron has no symbol for it. Quartz, Spring and EventBridge use L, but crontab does not. A workaround is to run on days 28 to 31 and let the command check that tomorrow is the 1st, as shown in the guide below.
Is the expression sent anywhere?
No. The parser, the explanation and the run times are all computed in your browser. Nothing you type is uploaded.