0 0 * * * — What does this cron expression mean?
0 0 * * * is the canonical daily cron job and is exactly what the @daily and @midnight shortcuts expand to. Midnight is a natural boundary for “close yesterday, open today” work such as report generation or partition rotation. It is also the most crowded minute on any shared system, and the minute where date logic is most likely to be off by one.
0 0 * * *
Run the job once a day at exactly 00:00, the start of each day, in the scheduler's timezone.
Frequency: 1 run per day. cronstrue reads it as “At 00:00”.
Open 0 0 * * * in the Cron BuilderField-by-field breakdown
0
Minute
0–59
0
Hour
0–23
*
Day of month
1–31
*
Month
1–12
*
Day of week
0–6
- Minute0 — at minute 0.
- Hour0 — at hour 0, which is midnight on the 24-hour clock.
- Day of month* — every day of the month.
- Month* — every month.
- Day of week* — every day of the week.
Next run times
Example: if it is Monday, 5 Jan 2026, 09:07 UTC, the next runs of 0 0 * * * (UTC) are:
- #1Tue, 6 Jan 2026, 00:00 UTC
- #2Wed, 7 Jan 2026, 00:00 UTC
- #3Thu, 8 Jan 2026, 00:00 UTC
- #4Fri, 9 Jan 2026, 00:00 UTC
- #5Sat, 10 Jan 2026, 00:00 UTC
Live times from your current clock replace this example once the page loads. Cron uses the scheduler's timezone; most cloud servers, GitHub Actions and AWS EventBridge rules use UTC.
0 0 * * * in Quartz, AWS, GitHub Actions, Kubernetes and systemd
Crontab (Linux / macOS)
0 0 * * * /usr/local/bin/job.sh >> /var/log/job.log 2>&1Standard 5-field syntax used by Vixie cron, cronie, busybox crond and most libraries (node-cron, APScheduler, robfig/cron).
Quartz (6 and 7 fields)
0 0 0 * * ?
0 0 0 * * ? *
# Spring @Scheduled
@Scheduled(cron = "0 0 0 * * *")Three zeros for second, minute and hour. Spring also accepts the macro @daily (or @midnight).
AWS EventBridge
cron(0 0 * * ? *)
# interval alternative
rate(1 day)cron(0 0 * * ? *) is midnight UTC. rate(1 day) runs every 24 hours from creation time, which is usually not midnight.
GitHub Actions
on:
schedule:
# Every day at midnight, evaluated in UTC
- cron: '0 0 * * *'Midnight UTC is one of the busiest moments for GitHub's scheduler. Nightly builds at 0 0 * * * are regularly delayed; a time like 37 0 * * * starts more reliably.
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: every-day-at-midnight
spec:
schedule: "0 0 * * *"
timeZone: "Etc/UTC"
concurrencyPolicy: Forbid
startingDeadlineSeconds: 3600
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: job
image: alpine:3.20
command: ["/bin/sh", "-c", "echo running"]Kubernetes also accepts @daily and @midnight in schedule. Set timeZone so “midnight” means the day boundary your business uses.
systemd timer
# /etc/systemd/system/myjob.timer
[Unit]
Description=Every day at midnight
[Timer]
OnCalendar=daily
Persistent=true
[Install]
WantedBy=timers.targetdaily is shorthand for *-*-* 00:00:00. Many distros already run timers at midnight, so consider RandomizedDelaySec=15min.
When to use every day at midnight
- Closing out daily totals and generating the previous day's report.
- Creating tomorrow's table partition or rotating daily indexes.
- Resetting per-day quotas, counters and rate-limit buckets.
- Publishing scheduled content or expiring daily promotions.
Common pitfalls with 0 0 * * *
% must be escaped in crontab commands
Midnight jobs often name files by date. In a crontab line, an unescaped % is turned into a newline and everything after it is passed to the command as stdin. date +%F silently breaks. Escape each % as \%, or move the command into a script.
# WRONG: the command is cut at the first %
0 0 * * * pg_dump app > /backups/app-$(date +%F).sql
# RIGHT
0 0 * * * pg_dump app > /backups/app-$(date +\%F).sqlWhich day is “today” at 00:00?
At 00:00:00 the date has already rolled over, so date returns the new day while the data you want to summarise belongs to yesterday. Compute the target date explicitly (date -d yesterday on GNU, date -v-1d on macOS) rather than assuming. If the job can start a few seconds early on another scheduler, it may even see the old date.
Midnight UTC vs your users' midnight, and DST at 00:00
On a UTC server, “end of day” for New York users is 04:00 or 05:00 UTC depending on the season. Set the scheduler's timezone instead of hard-coding an offset. Also note that a few zones, such as America/Santiago, change their clocks at midnight, so 00:00 local does not exist on the spring-forward day.
Related cron expressions
Every day at 2:00 AM
0 2 * * *
Every 6 hours
0 */6 * * *
Every day at 4:00 AM
0 4 * * *
Every hour
0 * * * *
Need a different schedule? Paste 0 0 * * * into the Cron Builder and edit it, browse all cron expressions, read the cron syntax guide or copy from the cron examples list.
Frequently Asked Questions
What does 0 0 * * * mean in cron?▾
Once a day at midnight. The first 0 is minute 0, the second 0 is hour 0, and the remaining * fields allow every day, month and weekday. It is identical to the @daily and @midnight shortcuts.
Is 0 0 * * * the same as @daily?▾
Yes. In Vixie cron, cronie, Kubernetes and most libraries, @daily and @midnight both expand to 0 0 * * *. Use whichever your team finds clearer; the explicit form is more portable to tools that don't support macros, such as AWS EventBridge.
What is 0 0 * * * in AWS EventBridge and Quartz?▾
AWS EventBridge: cron(0 0 * * ? *), which is midnight UTC. Quartz: 0 0 0 * * ? (second, minute, hour, then ? for day-of-week). Spring @Scheduled: 0 0 0 * * *.