About the Cron Expression Generator
Paste a cron expression or build one field by field, and the cron expression generator explains it in plain English with the next five run times. Pick the time zone your server uses, and you'll see when the job really fires, even on the night the clocks change.
It reads five-field expressions the way crontab, Kubernetes CronJobs and GitHub Actions do, six-field expressions with seconds first (Quartz, Spring, node-cron), and macros such as @daily. An AWS EventBridge expression gets an error that explains the field order instead of wrong run times. Everything runs in your browser, and AI agents can run the same check with explain_cron on the toolo MCP server.
- Write an expression in Cron expression, or click one of the Presets, such as Every 5 minutes or Weekdays at 9:00.
- Read the line under the box: "At 09:30, Monday through Friday", or the reason it's invalid, such as
minutes part must be >= 0 and <= 59for a60in the first field. - Check Next 5 runs. Time zone starts at Local time; set it to UTC or any zone under All time zones to match the machine that runs the job.
- To change one part, use Build it field by field: type into Minute, Hour, Day of month, Month or Day of week, or click a chip such as
*/15,9-17orL. It handles five-field expressions only. - A Note under the description means your step doesn't divide the hour or day evenly; it lists the real minutes or hours.
- Click Copy to get the expression with single spaces, ready for
crontab -eor a YAML file.
Input*/15 * * * *
Time zone: UTCOutputEvery 15 minutes
Wed, Oct 7, 2026, 12:15 UTC
Wed, Oct 7, 2026, 12:30 UTC
Wed, Oct 7, 2026, 12:45 UTCUnless stated otherwise, run times on this page start from Wednesday 7 October 2026, 12:00 UTC, with Time zone set to UTC.
Input30 2 * * *
Time zone: America/New_YorkOutputAt 02:30
Sun, Mar 8, 2026, 03:30 EDT
Mon, Mar 9, 2026, 02:30 EDT
Tue, Mar 10, 2026, 02:30 EDTCounted from Saturday 7 March 2026. On 8 March, 02:30 doesn't exist in New York, so the run moves to 03:30. Your cron daemon may handle it differently.
Input*/35 * * * *OutputEvery 35 minutes
Note: */35 restarts every hour: it runs at minute 0, 35, so the gap is not always 35 minutes.
Wed, Oct 7, 2026, 12:35 UTC
Wed, Oct 7, 2026, 13:00 UTC
Wed, Oct 7, 2026, 13:35 UTCThe gaps alternate between 35 and 25 minutes. Hours behave the same: 0 */5 * * * runs at 0, 5, 10, 15 and 20.
Input0 18 ? * MON-FRI *OutputNot a valid cron expression: this looks like an AWS EventBridge expression (minute hour day month weekday year). toolo reads 6 fields as seconds first. Drop the year and use * instead of ?, for example 0 10 * * *Test it here as 0 18 * * 1-5, then put the ? and the year back for AWS.
Cron syntax: fields and special characters
A standard cron expression has five fields: minute (0 to 59), hour (0 to 23), day of month (1 to 31), month (1 to 12 or JAN to DEC) and day of week (0 to 6 or SUN to SAT, where 0 and usually 7 are Sunday).
*, ,, - and / work everywhere. L, #, W and ? come from Quartz, Spring and AWS, and Linux crontab doesn't accept them.
*any value,,a list (1,15),-a range (1-5is Monday to Friday)./a step:*/15in minutes is 0, 15, 30 and 45, and10-50/20is 10, 30 and 50. Steps restart every hour or day.Llast: the last day of the month, or5L, the last Friday.#nth weekday:5#2is the second Friday. Both work here.Wnearest weekday (15W) gets an error here.?means no specific value and works like*in the day fields.- Macros:
@yearlyand@annually(0 0 1 1 *),@monthly,@weekly,@dailyand@midnight(0 0 * * *),@hourly.@rebootruns once at startup, so it has no next run. GitHub Actions takes no macros.
Common cron schedules
The generator's description, then the first run from the start time above:
*/5 * * * *: Every 5 minutes. 12:05.0 * * * *: Every hour. 13:00.0 */6 * * *: On the hour, every 6 hours (00, 06, 12, 18). 18:00.0 8,20 * * *: At 08:00 and 20:00. 20:00.0 0 * * *: At 00:00, the same as@daily. Thu, Oct 8.0 9-17 * * 1-5: Every hour, between 09:00 and 17:00, Monday through Friday. 13:00.0 0 * * 0: At 00:00, only on Sunday. Sun, Oct 11.0 0 1 */3 *: At 00:00, on day 1 of the month, every 3 months (Jan, Apr, Jul, Oct). Fri, Jan 1, 2027.0 12 * * 5#2: At 12:00, on the second Friday of the month. Fri, Oct 9.*/30 * * * * *: Every 30 seconds (six fields). 12:00:30.0 0 */2 * *isn't every other day. It hits the odd days of the month, so it runs on Oct 31 and again on Nov 1.- Every 90 minutes needs two lines,
0 0-21/3 * * *and30 1-22/3 * * *, because*/90in the minute field means minute 0 of every hour.
Day of month and day of week: the OR rule
When both day fields are set (neither is *), cron runs the job when either one matches. So 0 0 13 * 5 isn't Friday the 13th: the generator says "At 00:00, on day 13 of the month, and on Friday" and lists Fri, Oct 9, then Tue, Oct 13.
To require both, set one field and test the other in the command: 0 0 13 * * [ "$(date +\%u)" = 5 ] && /path/to/job. Linux crontab has no L, so month end works the same way: 0 0 28-31 * * [ "$(date -d tomorrow +\%d)" = 01 ] && /path/to/job with GNU date. Don't use 0 0 31 * *; it skips every shorter month.
Time zones and daylight saving time
Linux cron uses the server's local time zone; cronie (Fedora, RHEL) also reads a CRON_TZ= line. Kubernetes uses .spec.timeZone, or else the kube-controller-manager's zone. GitHub Actions uses UTC unless you add timezone. EventBridge Scheduler takes a zone per schedule; older EventBridge rules use UTC. On a UTC server, 0 9 * * 1-5 fires at 14:30 in Kolkata and 06:00 in São Paulo.
Runs in an hour the clocks skip or repeat differ per system. Debian's cron runs skipped jobs soon after the change and doesn't repeat them; cronie's manual pages contradict each other. EventBridge Scheduler skips the spring run and runs once in autumn. GitHub Actions moves the run to the next valid time, and so does the generator: 0 2 * * 0 in Europe/Berlin shows Sun, Mar 29, 2026, 03:00, and 30 2 * * * in Australia/Sydney shows Sun, Oct 4, 03:30.
The safe choice is a UTC schedule, or no jobs between 01:00 and 03:00 local time. The Unix Timestamp Converter shows any UTC moment in your users' zones.
Crontab, Kubernetes, GitHub Actions, AWS and Quartz
- Linux crontab:
crontab -eedits,crontab -lprints,crontab -rdeletes everything without asking. Lines in/etc/crontaband/etc/cron.d/have a user name before the command, and on Debian and Ubuntu a file there with a dot in its name, likebackup.cron, is ignored. - Kubernetes CronJob:
.spec.scheduletakes five fields or a macro..spec.timeZone(stable since v1.27) takes an IANA name;CRON_TZorTZinside the schedule fails validation. - GitHub Actions: five fields, at most every 5 minutes, on the default branch. Runs can be late at busy times such as the top of the hour, and stop in public repositories after 60 days without activity.
- AWS EventBridge:
cron(minutes hours day-of-month month day-of-week year), day of week 1 to 7 for SUN to SAT, and?in one day field, as incron(0 18 ? * MON-FRI *). - Quartz and Spring: seconds first. Quartz has 6 or 7 fields (a 7th year field gets an error here), counts 1 to 7 for SUN to SAT and needs
?in one day field. Spring's@Scheduleduses 6 fields and 0 or 7 for Sunday. So6is Friday in Quartz and AWS but Saturday in crontab.
Why a cron job doesn't run
If the schedule looks right here but nothing happens, check these first:
- Cron doesn't load your shell profile, so
nodeorpython3from a version manager isn't onPATH. Use full paths, or setPATHin the crontab. - Output goes to local mail and is lost if mail isn't set up. Append
>> file.log 2>&1to see the error. %starts a new line in a crontab command. Writedate +\%F, notdate +%F.- The last line has no newline at the end, so cron treats it as broken.
- The script isn't executable, or it needs an environment variable that only your terminal has.
- The server's time zone isn't what you assumed. Run
dateon the server and set Time zone here to match.
Where to put the expression
The same kind of schedule in the places you're most likely to use it. In YAML, quote the schedule: an unquoted */15 * * * * fails with unidentified alias "/15", as the YAML to JSON converter shows.
# ┌───────────── minute (0-59)
# │ ┌─────────── hour (0-23)
# │ │ ┌───────── day of month (1-31)
# │ │ │ ┌─────── month (1-12 or JAN-DEC)
# │ │ │ │ ┌───── day of week (0-6 or SUN-SAT, 0 and 7 are Sunday)
# │ │ │ │ │
# * * * * * command
PATH=/usr/local/bin:/usr/bin:/bin
30 2 * * * /home/deploy/backup.sh >> /home/deploy/backup.log 2>&1# /etc/cron.d/backup (no dot in the file name)
PATH=/usr/local/bin:/usr/bin:/bin
# m h dom mon dow user command
30 2 * * * deploy /home/deploy/backup.sh >> /home/deploy/backup.log 2>&1apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "30 2 * * *"
timeZone: "Europe/Berlin"
jobTemplate:
spec:
template:
spec:
containers:
- name: report
image: busybox:1.36
command: ["sh", "-c", "date"]
restartPolicy: OnFailureon:
schedule:
- cron: "30 5 * * 1-5"
timezone: "America/New_York"@Scheduled(cron = "0 30 9 * * MON-FRI", zone = "Asia/Singapore")
public void sendDailyReport() {
// 09:30 Singapore time, Monday to Friday
}What is a cron expression?
A short schedule string that tells cron or another scheduler when to run a job. The five fields are minute, hour, day of month, month and day of week, so 0 3 * * * means every day at 03:00.
What does */5 * * * * mean?
Every 5 minutes: at minutes 0, 5, 10 and so on up to 55, in every hour of every day.
How do I run a cron job every 30 seconds?
Standard cron counts in minutes, so use two lines: * * * * * /path/to/job and * * * * * sleep 30; /path/to/job. Schedulers with seconds accept */30 * * * * *.
Is Sunday 0 or 7 in cron?
Both. In crontab, 0 and 7 mean Sunday, and the generator accepts either. Quartz and AWS EventBridge count from 1, where 1 is Sunday.
What is the difference between 5-field and 6-field cron expressions?
Five fields start with minutes. Six usually add seconds at the start (Quartz, Spring, node-cron), but in AWS EventBridge the sixth is a year at the end. The generator reads six fields as seconds first.
How do I check if my cron job ran?
Look in the cron log: journalctl -u cron on Debian and Ubuntu, journalctl -u crond or /var/log/cron on Fedora and RHEL. It shows that the job started; redirect the job's output to a file to see errors.