Quick answer
The cron expression for every 12 hours is 0 */12 * * *. The */12 step in the hour field keeps hours 0 and 12 from the range 0 to 23, and the 0 in the minute field runs the job on the hour, so it fires at midnight and noon every day. Shift both runs with a range, for example 0 6-23/12 * * * for 06:00 and 18:00.
- Live next runs
- Any time zone
- Field-by-field breakdown
- Seven platform snippets
- Daylight saving aware
How to use this schedule
- 1Copy
0 */12 * * *with the Copy expression button. - 2Check Next runs in your time zone to confirm it fires when you expect, including around daylight saving changes.
- 3Pick your platform under Use it on your platform and copy the ready-made crontab line, workflow, manifest or timer.
- 4Need a different time or day? Click Customize to open it in the cron expression generator and change any field.
How does the */12 step work?
A step selects every nth value of a field, starting from the field's minimum. The hour field runs from 0 to 23, so */12 keeps 0 and 12, and nothing else fits. The sequence restarts every day: cron does not remember the previous run or count twelve hours from it. The "every 12 hours" rhythm comes entirely from the calendar.
Twelve works because it divides 24. Steps that don't divide 24 look like intervals but aren't:
| Expression | Runs at | Gaps |
|---|---|---|
0 */12 * * * | 00:00, 12:00 | 12 h, 12 h |
0 6-23/12 * * * | 06:00, 18:00 | 12 h, 12 h |
0 */9 * * * | 00:00, 09:00, 18:00 | 9 h, 9 h, then 6 h |
0 */16 * * * | 00:00, 16:00 | 16 h, then 8 h |
To move the pair, start the range at any hour from 0 to 11: 0 9-23/12 gives 09:00 and 21:00, and 30 7-23/12 gives 07:30 and 19:30.
Should I use */12 or a list of two hours?
For midnight and noon they are identical: 0 */12 * * * and 0 0,12 * * * match the same two times. The difference is intent. The step tells the next reader "evenly spaced, twelve hours apart", while a list says "these two specific times" and lets you choose uneven ones such as 08:00 and 17:00. If that is what you really need, see twice a day.
Two runs a day also means each run carries a lot of weight. If the server is down at noon, cron simply skips that run; it never catches up. Design the job to process everything since its last successful run rather than "the last 12 hours", and the occasional missed or late run stops mattering. For more frequent checkpoints, every 6 hours doubles the cadence; for once a day, see every day at midnight.
What does each field in 0 */12 * * * mean?
| Field | Value | Allowed | Meaning |
|---|---|---|---|
| Minute | 0 | 0–59 | at minute 0 (on the hour) |
| Hour | */12 | 0–23 | every 12 hours: 00:00 and 12:00 |
| Day of month | * | 1–31 | every day of the month |
| Month | * | 1–12, JAN–DEC | every month |
| Day of week | * | 0–7 (0 and 7 are Sunday), SUN–SAT | every day of the week |
Read together: At midnight and noon (00:00 and 12:00) every day.
How do I adjust 0 */12 * * * to my own schedule?
Small edits to 0 */12 * * * cover most real-world needs:
| Expression | What it does |
|---|---|
0 6-23/12 * * * | Every 12 hours at 06:00 and 18:00 |
0 9-23/12 * * * | Every 12 hours at 09:00 and 21:00 |
0 0,12 * * * | The same midnight-and-noon schedule written as a list |
30 */12 * * * | Every 12 hours at 00:30 and 12:30 |
0 */12 * * 1-5 | Every 12 hours on weekdays only |
Need something else? Click Customize at the top of the page to open this schedule in the cron expression generator and change any field.
Related schedules: Twice a day · Every 6 hours · Every day at midnight · Every day at noon
Browse all schedules in the cron schedule library.
How do I run 0 */12 * * * in crontab, GitHub Actions, Kubernetes and the cloud?
| Platform | Write it as | Time zone |
|---|---|---|
| Linux crontab | 0 */12 * * * | Server's time zone; CRON_TZ= in cronie |
| GitHub Actions | - cron: "0 */12 * * *" | UTC by default; add timezone: (IANA name) |
| Kubernetes CronJob | schedule: "0 */12 * * *" | Set timeZone: (1.27+) |
| Cloudflare Workers | 0 */12 * * * | UTC only; numbers weekdays from 1 = Sunday, so use names |
| Vercel Cron Jobs | 0 */12 * * * | UTC only; more than once a day needs Pro (Hobby: once a day) |
| AWS EventBridge Scheduler | cron(0 */12 * * ? *) | Takes a time zone; legacy scheduled rules are UTC only |
| systemd timer | OnCalendar=*-*-* 00,12:00:00 | Add a zone after the time, e.g. Europe/London |
In a crontab (crontab -e), the full line looks like this:
0 */12 * * * /path/to/job.sh >> /var/log/job.log 2>&1The live panel at the top of the page builds complete, copy-ready files for each platform (workflow, CronJob manifest, wrangler.toml, vercel.json, AWS CLI and systemd units) and can shift the schedule to UTC for platforms that need it.
What can go wrong with 0 */12 * * *?
- Steps only divide evenly when they divide the range.
*/12is fine for 24 hours, but*/16or*/9leave a short gap before midnight because the count restarts every day. */12 * * * *is every 12 minutes (at :00, :12, :24, :36, :48), which is a very different job from twice a day.- One of the two runs is usually at night for someone. If the job emails people or calls a partner API with business-hours limits, pick the phase deliberately instead of defaulting to midnight.
- A missed run is simply skipped by cron. If the job must catch up, make it process everything since the last success, or use a systemd timer with
Persistent=true. - In a zone with daylight saving time, a schedule with
*in the minute or hour field follows the wall clock: the spring-forward night loses an hour of runs and the fall-back night repeats one. Servers on UTC never see this.
Frequently asked questions
Last updated by the Playxoft engineering team.