cronuru
Pattern

Business Hours (Hourly, 9 AM–5 PM Weekdays)

0 9-17 * * 1-5
0 0 9-17 ? * MON-FRI
0 9-17 * * 1-5
0 9-17 ? * MON-FRI *
0 0 9-17 * * MON-FRI
0 9-17 * * 1-5

Runs hourly at :00 from 09:00 to 17:00, Monday through Friday — 9 runs per weekday, none overnight or on weekends.

Use in your stack

# Hourly during business hours, US Eastern
CRON_TZ=America/New_York
0 9-17 * * 1-5 /usr/local/bin/business-hours-job.sh
{ "cron": "0 0 9-17 ? * MON-FRI", "timezone": "America/New_York" }
apiVersion: batch/v1
kind: CronJob
metadata:
  name: business-hours-job
spec:
  schedule: "0 9-17 * * 1-5"
  timeZone: "America/New_York"
  jobTemplate:
    spec:
      template:
        spec:
          containers:
          - name: job
            image: my-image:latest
          restartPolicy: OnFailure
cron(0 9-17 ? * MON-FRI *)
@Scheduled(cron = "0 0 9-17 * * MON-FRI", zone = "America/New_York")
public void businessHours() { /* ... */ }
on:
  schedule:
    - cron: '0 9-17 * * 1-5'   # hourly 09:00-17:00 UTC, Mon-Fri

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-19T16:00:00.000Z
  3. 032026-08-19T17:00:00.000Z
  4. 042026-08-20T09:00:00.000Z
  5. 052026-08-20T10:00:00.000Z
  6. 062026-08-20T11:00:00.000Z
  7. 072026-08-20T12:00:00.000Z
  8. 082026-08-20T13:00:00.000Z
  9. 092026-08-20T14:00:00.000Z
  10. 102026-08-20T15:00:00.000Z

Variations

Common use cases

  • Polling or syncing only while the business is open.
  • Sending notifications during working hours so they're seen.
  • Refreshing dashboards during the workday.
  • Rate-limited API calls confined to business hours.

Gotchas

  • The `9-17` range in the hour field is inclusive of both ends — it fires at 9, 10, 11, …, 17 (9 AM through 5 PM), which is 9 firings.
  • Day-of-week numbering: Unix uses `1-5` (Mon-Fri). Quartz uses `MON-FRI`. Use name form to avoid the off-by-one.
  • Timezone matters most here — "business hours" is meaningless without a pinned local timezone.
  • AWS EventBridge: `0 9-17 ? * MON-FRI *`.

0 9-17 * * 1-5 is the business-hours schedule — hourly during the workday, silent overnight and on weekends. The inclusive hour range and the mandatory timezone pin are the two things to get right. Combine the range with a minute step (*/30) for sub-hourly business-hours cadence.

Frequently asked questions

What does `0 9-17 * * 1-5` mean?
Minute `0`, hour `9-17` (a range — 9 AM through 5 PM inclusive), day-of-month `*` (any), month `*` (any), day-of-week `1-5` (Monday through Friday). So the job fires at the top of every hour from 9 AM to 5 PM on weekdays — 9 times per weekday.
Does `9-17` include 5 PM?
Yes. Cron ranges are inclusive of both endpoints, so `9-17` fires at 9, 10, 11, 12, 13, 14, 15, 16, and 17 — that's 9 AM through 5 PM, nine firings. If you want to stop at 4 PM, use `9-16` (eight firings).
How do I run every 30 minutes during business hours instead of hourly?
Add a step to the minute field: `*/30 9-17 * * 1-5` fires at :00 and :30 of every hour from 9 AM to 5 PM on weekdays. `*/15 9-17 * * 1-5` fires every 15 minutes.
Why is the timezone so important here?
"Business hours" is defined entirely by local time — 9 AM in one timezone is the middle of the night in another. Always pin the timezone (`CRON_TZ`, `spec.timeZone`, or Spring's `zone`). On UTC-only schedulers like EventBridge and GitHub Actions, offset the hour range to match your target timezone.

More hours schedules

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