cronuru
Pattern

Every Odd Hour

0 1-23/2 * * *
0 0 1/2 * * ?
0 1-23/2 * * *
0 1-23/2 * * ? *
0 0 1-23/2 * * *
0 1-23/2 * * *

Runs at 01:00, 03:00, 05:00, …, 23:00 — 12 invocations a day on odd hours. The range start `1-23` is what shifts the step off even hours.

Use in your stack

# Odd hours — 01:00, 03:00, ..., 23:00
0 1-23/2 * * * /usr/local/bin/odd-hours.sh

# The even-hour counterpart, for contrast
0 */2 * * * /usr/local/bin/even-hours.sh
{ "cron": "0 0 1/2 * * ?", "timezone": "UTC" }
apiVersion: batch/v1
kind: CronJob
metadata:
  name: odd-hours
spec:
  schedule: "0 1-23/2 * * *"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: odd-hours
            image: my-image:latest
          restartPolicy: OnFailure
cron(0 1-23/2 * * ? *)
@Scheduled(cron = "0 0 1-23/2 * * *")
public void everyOddHour() { /* ... */ }
on:
  schedule:
    - cron: '0 1-23/2 * * *'   # odd hours, UTC

Next runs

Pick a timezone to see when this expression fires next.

Next 10 runs
  1. 012026-08-19T15:00:00.000Z
  2. 022026-08-19T17:00:00.000Z
  3. 032026-08-19T19:00:00.000Z
  4. 042026-08-19T21:00:00.000Z
  5. 052026-08-19T23:00:00.000Z
  6. 062026-08-20T01:00:00.000Z
  7. 072026-08-20T03:00:00.000Z
  8. 082026-08-20T05:00:00.000Z
  9. 092026-08-20T07:00:00.000Z
  10. 102026-08-20T09:00:00.000Z

Variations

0 */2 * * *

Every even hour — the `*/2` default phase

0 * * * *

Every hour

0 */3 * * *

Every 3 hours

0 9-17 * * 1-5

Hourly during business hours

Common use cases

  • Staggering a job so it never collides with the `*/2` even-hour schedules everything else uses.
  • Interleaving two 2-hourly jobs so one runs on even hours and the other on odd.
  • Spreading load away from the top-of-even-hour spike on shared infrastructure.
  • Alternating a pair of replicas or regions on a 2-hour cadence.

Gotchas

  • **`*/2` can never produce odd hours.** The step operator means "start at the field minimum, then keep adding the step." The hour field's minimum is 0, so `*/2` yields 0, 2, 4, … 22 — always even. There is no modifier that shifts a bare `*/n`.
  • **The range start is the offset.** `1-23/2` reads as "over the range 1 through 23, take every 2nd value," so counting begins at 1. The upper bound matters less than the lower one — `1-23/2` and `1-22/2` produce the same 12 values here, but always write the real bound so the intent is readable.
  • `0 1-23/2 * * *` and `0 1,3,5,7,9,11,13,15,17,19,21,23 * * *` are identical. Use the explicit list if your team finds the step syntax easy to misread.
  • **Quartz uses `start/step` rather than `range/step`.** Write `0 0 1/2 * * ?` — the `1/2` means "from 1, every 2nd" and runs to the end of the field automatically.
  • Odd hours are not symmetric across a day boundary the way even hours are: the gap from 23:00 to the next 01:00 is still 2 hours, so the cadence holds through midnight. It's the *daylight-saving* transitions that break it, not the date change — a spring-forward skips one firing and a fall-back repeats one.
  • AWS EventBridge needs the 6-field form with a `?` placeholder: `cron(0 1-23/2 * * ? *)`.

0 1-23/2 * * * fires twelve times a day, on the odd hours: 01:00, 03:00, 05:00, and so on through 23:00.

The interesting part is not the schedule — it’s why the obvious version doesn’t work.

*/2 is not “every 2 hours from wherever”

The step operator has one rule that catches nearly everyone: it always begins at the field’s minimum value. Writing */2 in the hour field means “start at 0, add 2, keep going while the value is still in range,” which produces:

0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22

Even hours, every time. There is no flag, prefix or suffix that shifts a bare */n onto a different phase. The * is doing real work in that expression — it stands for the field’s full range, 0-23, and the step counts from the start of whatever range precedes it.

The fix: give the step a range to count from

Replace the * with an explicit range whose lower bound is where you want counting to begin:

0 1-23/2 * * *

Now the step walks 1-23 instead of 0-23, producing 1, 3, 5, … 23. The lower bound is the offset; the upper bound just needs to be at least as large as the last value you want.

This generalises to every field. 5-59/15 * * * * fires at :05, :20, :35 and :50 rather than the usual quarter-hour marks — the same one-character idea, applied to minutes. The cron offset guide covers the pattern in full, including how to stagger a whole fleet of jobs away from the top of the hour.

If the step syntax reads badly to you, the explicit list is exactly equivalent and there is no cost to preferring it:

0 1,3,5,7,9,11,13,15,17,19,21,23 * * *

Quartz says it differently

Quartz and AWS EventBridge support a start/step form that the Unix family does not:

0 0 1/2 * * ?

Read as “from hour 1, every 2nd hour, through the end of the field.” No upper bound needed. The Unix 1-23/2 and the Quartz 1/2 describe the same twelve firings — see the Quartz dialect reference and the dialect comparison for where else the two families diverge.

Why you’d want odd hours

Almost always: because everything else is on even hours.

0 */2 * * * is the path of least resistance, so on any shared host or cluster the even hours accumulate jobs while the odd ones sit empty. Moving a job to 0 1-23/2 * * * costs nothing, keeps the same two-hour cadence, and guarantees it never contends with the even-hour crowd.

The same reasoning gives you a clean interleave. Put one job on 0 */2 * * * and its partner on 0 1-23/2 * * *, and you have two schedules that each fire twelve times a day and never once collide — useful for alternating replicas, or for a producer and consumer that must not overlap.

One caveat: daylight saving

Odd hours survive midnight fine — the gap from 23:00 to the next day’s 01:00 is still two hours. What they don’t survive is a DST transition in a local-time crontab. Springing forward skips an hour outright, so one firing simply never happens; falling back repeats an hour, so one firing happens twice. That applies equally to the even-hour version, and the fix is the same: pin the job to UTC with CRON_TZ=Etc/UTC, or accept two anomalous days a year.

Frequently asked questions

What is the cron expression for every odd hour?
`0 1-23/2 * * *`. It fires at 01:00, 03:00, 05:00, 07:00, 09:00, 11:00, 13:00, 15:00, 17:00, 19:00, 21:00 and 23:00 — twelve runs a day. The range `1-23` sets where the step starts counting; without it, the step falls back to the field minimum of 0 and you get even hours instead.
Why does `0 */2 * * *` only run on even hours?
Because the step operator always anchors at the field's minimum value. `*/2` in the hour field means "start at 0, then add 2 repeatedly while still in range," producing 0, 2, 4 and so on up to 22. The hour field's minimum is 0 and there is no way to tell a bare `*/n` to begin anywhere else — the only mechanism for moving the starting point is to replace the `*` with an explicit range, as in `1-23/2`.
What is the cron expression for every even hour?
`0 */2 * * *`, which is the same schedule as `0 0-22/2 * * *` and as the explicit list `0 0,2,4,6,8,10,12,14,16,18,20,22 * * *`. Because the step already anchors at 0, no range is needed. See [every 2 hours](/every-2-hours) for the full breakdown of that schedule.
Does `1-23/2` behave the same in every cron dialect?
In the Unix family, yes — crontab, Kubernetes CronJob, GitHub Actions, Vercel and Cloudflare Workers all accept `range/step` with the same meaning. Quartz and AWS EventBridge additionally support a `start/step` form, so Quartz prefers `1/2` — "from 1, every 2nd, to the end of the field." Both express the same twelve hours; only the notation differs.
How do I interleave two jobs so they never run at the same time?
Give one `0 */2 * * *` and the other `0 1-23/2 * * *`. Each fires twelve times a day at a two-hour cadence, and the two schedules share no firing times at all — one owns the even hours, the other the odd. This is the simplest form of cron [offsetting](/guides/cron-offset), and the same technique works in the minute field for spreading jobs away from the top of the hour.

More hours schedules

Other patterns on the same cadence — or browse every schedule.