TechCompare LogoTechCompare

Run a cron job daily at midnight: 0 0 * * * explained

0 0 * * * is correct for daily midnight execution, but always confirm the server timezone first. A job you think runs at midnight local time might actually be firing in the middle of the afternoon. Document the intended timezone next to the cron expression in your crontab.

0 0 * * * runs a job at exactly midnight (00:00) every day. The first zero fixes the minute to :00, the second zero fixes the hour to 0 (midnight in 24-hour time). This is the standard pattern for daily database backups, report generation, and log summarization.

By TechCompare · Updated

Schedule pattern
Daily at midnight
daily-midnight
Category
Common Patterns
Standard cron expression patterns

How this is calculated

Midnight cron jobs run in the server's local timezone, which is typically UTC on cloud VMs and containerized environments. A 0 0 * * * job on a UTC server runs at 00:00 UTC, which might be 5 PM or 8 PM in your local time depending on your timezone. If you need the job to run at local midnight, either set the server's timezone or adjust the hour field: for EST (UTC-5), use 0 5 * * *. The @daily and @midnight shortcuts are equivalent to 0 0 * * *.

Verdict

Midnight is a timezone-relative concept, and that's where most daily-cron bugs hide. Cloud VMs and containers default to UTC, so a 0 0 * * * job fires at 00:00 UTC, which lands at 5 PM PST or 8 PM EST. Either set the server timezone, shift the hour (0 5 for EST midnight), or rely on the @daily shorthand once you've confirmed the reference frame.

More Cron scenarios

Frequently asked questions

How do I run a cron job every day at midnight?
Use 0 0 * * *. The first zero is the minute, the second zero is hour 0 in 24-hour time, and the job fires at exactly 00:00 daily. Daily database backups, report generation, and log summarization are the standard midnight workloads because nobody is awake to notice the disk thrash.
Why does my midnight cron job run at the wrong time?
Almost always a timezone mismatch. Cloud VMs and Docker containers default to UTC, so your 0 0 * * * fires at 00:00 UTC, which is 5 PM or 8 PM US local time depending on the coast and daylight saving. Check with the date command on the server, then either set CRON_TZ in the crontab or shift the hour field to match UTC.
Is there a difference between @daily and 0 0 * * *?
No, @daily expands to exactly 0 0 * * *, and so does @midnight. The shortcuts read better in a crontab and carry the same caveat: they evaluate against the server's local timezone. If you move the crontab to a container running BusyBox cron, the @ forms stop working, so numeric expressions are the portable choice.