Paste a cron expression to see what it does: a plain-English description, every field broken out, and the next ten times it will fire in your time zone. The Examples dropdown loads common schedules such as every 15 minutes, weekdays at 09:00 and the first of the month, so you can edit one instead of starting from scratch.
* * * * * │ │ │ │ │ │ │ │ │ └─ day of week (0-7, Sunday is 0 and 7) │ │ │ └─── month (1-12) │ │ └───── day of month (1-31) │ └─────── hour (0-23) └───────── minute (0-59)
Each field takes a value, a list (1,15), a range
(1-5), a step (*/10) or *.
There is no seconds field, so one minute is the finest schedule
standard cron supports. A six-field expression comes from Quartz
or Spring, and this page flags it instead of guessing what it
means.
0 9 1 * 1 looks like "the 1st of the month, if it is
a Monday". However, when both day-of-month and day-of-week are
restricted, POSIX cron fires when either matches, so this
expression runs on the 1st of every month and on every Monday.
Pick The either-or trap from Examples and read the run list.
Restrict one day field and check the other in your
script. Standard cron cannot express "Friday the 13th".
For example, run 0 9 13 * * and have the script exit
unless the day is a Friday.
The runs above are in your browser's zone, named next to Next runs. Servers and containers usually run in UTC, so a job that reads as 09:00 here may fire at a different local hour on the machine.
Put CRON_TZ=Europe/Berlin at the top of a crontab on cronie, or set the timeZone field on a Kubernetes CronJob. If you guess the host's zone instead, a 02:00 backup can end up running at lunchtime.
Implementations disagree about daylight saving. A job in the skipped spring hour may not run at all, and one in the repeated fall hour may run twice.
Run cron in UTC. UTC has no daylight saving, so the skipped and repeated hours never occur. Convert to local time only when a person reads the schedule.
crontab -e # edit
crontab -l # list
# Set the zone explicitly rather than guessing the host's
CRON_TZ=Europe/Berlin
0 9 * * 1-5 /usr/local/bin/report.sh
# cron runs with a nearly empty environment and a minimal PATH.
# Use absolute paths, and capture output or you will never see
# why it failed:
0 3 * * * /usr/bin/php /srv/app/artisan backup >> /var/log/backup.log 2>&1
# A % in a crontab line becomes a newline unless escaped
0 0 * * * /bin/echo $(date +\%F) The near-empty environment is the most common cron bug: a script that works in your shell fails at 03:00 because PATH, HOME and the virtualenv are not what you assumed.
apiVersion: batch/v1
kind: CronJob
metadata:
name: nightly-report
spec:
schedule: "0 9 * * 1-5"
timeZone: "Europe/Berlin" # stable since Kubernetes 1.27
concurrencyPolicy: Forbid # do not start if the last one is still running
startingDeadlineSeconds: 300 # skip rather than pile up after an outage
successfulJobsHistoryLimit: 3
jobTemplate:
spec:
backoffLimit: 2
template:
spec:
restartPolicy: OnFailure
containers:
- name: report
image: app:2.4.0
command: ["./report.sh"] // npm i cron-parser cronstrue
const parser = require("cron-parser");
const cronstrue = require("cronstrue");
console.log(cronstrue.toString("0 9 * * 1-5"));
// "At 09:00 AM, Monday through Friday"
const it = parser.parseExpression("0 9 * * 1-5", {
tz: "Europe/Berlin", // never rely on the host's zone
currentDate: new Date(),
});
for (let i = 0; i < 5; i++) console.log(it.next().toISOString()); Standard cron cannot express Friday the 13th, the last weekday of the month, or every second Tuesday. Quartz added L, W and # for these cases, and systemd timers use a different OnCalendar syntax. For such a schedule, we recommend running the job daily and putting the real condition at the top of the script.
This tool follows the specifications below. Read them when you need the exact normative wording, for example to settle an edge case between two implementations.
The generator builds an expression by clicking. The parser works the other way: paste an expression you already have, and it describes it in plain English and lists the next ten times it will fire.
Your browser's, named in the Next runs header. Cron usually runs somewhere else: servers and containers are typically on UTC, so a job that reads as 09:00 here may fire at a different local hour on the machine.
When both day-of-month and day-of-week are restricted, POSIX cron matches either one, not both. That expression fires on the 1st of every month and also every Monday. Restrict only one of the two fields.
It supports standard five-field cron plus the common shorthands: @hourly, @daily, @weekly, @monthly, @yearly and @midnight. Six-field expressions with seconds are a Quartz and Spring extension, and the parser flags them instead of guessing.
Implementations disagree, so avoid scheduling anything between 01:00 and 03:00 local time. A job in the skipped hour may not run at all, and one in the repeated hour may run twice. UTC has no daylight saving, so running cron in UTC avoids both cases.
*/15 * * * *, the first entry in Examples. The step counts from the start of the minute field, so it fires at :00, :15, :30 and :45 of every hour. The same shape works for any step that divides 60: */5, */10, */20 and */30. For every 2 hours use 0 */2 * * *, with the minute pinned to 0, or it fires every minute of those hours.
Use 0 9 * * 1-5: minute 0, hour 9, any day of the month, any month, Monday to Friday. Days of the week are numbered from Sunday, which is 0 or 7, so 30 3 * * 0 is Sundays at 03:30 and 0 18 * * 6,0 is weekends at 18:00. Load Weekdays at 09:00 from Examples and read the next runs, remembering that 9 means 9 in the zone the server uses.
The expression 0 0 1 * * runs at midnight on the 1st; pick First of the month from Examples to see the next ten dates. A list works in the same field, so 0 0 1,15 * * runs on the 1st and 15th and 0 0 1 1,4,7,10 * runs quarterly. Standard cron has no last-day-of-month value, so schedule 0 0 28-31 * * and have the script exit unless tomorrow is the 1st.
To build an expression by clicking instead of reading one, use the cron generator. The runs shown here are in your zone, so use the time zone converter to see them in the server's.