0 0 * * * runs the job once a day at midnight, meaning 0:00 — the first minute of the new day, not the last minute of the old one. Minute and hour are pinned to zero while day, month and weekday stay open. The shortcuts @daily and @midnight expand to this same line.
Which day does the midnight run belong to?
To the new one. A job that starts at 0:00 on Tuesday sees Tuesday's date, so a report meant to summarise Monday has to subtract a day explicitly, for example with date -d yesterday. This single off-by-one produces more empty reports than any other cron mistake, because the script runs fine and simply looks at a day that has barely begun.
Is midnight a good time for backups?
It is the busiest slot on most machines: log rotation, database dumps, cleanup jobs and half the crontabs on the planet start at 0:00. If your backup competes with all of them, it takes longer and is more likely to hit a locked file. Moving to 2:30 or 3:15 usually gives a quieter window with no downside.
What if the machine is switched off at midnight?
Plain cron simply skips the run; it has no memory of missed jobs. Laptops and office machines therefore need anacron, which tracks the last successful run and catches up after boot, or a systemd timer with Persistent=true. On an always-on server this does not matter, which is why the topic surprises people when they move a job to a desktop.
How to add the expression
- Decide whether the job needs yesterday's data; if so, compute the date inside the script instead of relying on the run day.
- Add 0 0 * * * plus the command to the crontab, or write @daily if the file is only read by humans.
- Consider moving to a quieter minute such as 0 2 * * * when the job is heavy.
- Log the start and end time so you can see later whether a run was skipped.