Regex and cron

Cron Expression for Business Hours (Every Hour)

On the hour from 09:00 to 17:00, Monday to Friday. Copy it, check the next runs in your time zone and grab a snippet for your platform.

  • Free foreverNo trial, no paywall, no usage limits.
  • No sign-upOpen the page and start. We never ask for an email to use a tool.
  • PrivateEverything runs in your browser. Your input is never uploaded or stored on our servers.
  • Works offlineOnce the page has loaded, the tool keeps working without a connection.

Cron expression

0 9-17 * * 1-5
Customize
0minuteMinute: at minute 0 (on the hour)9-17hourHour: every hour from 09:00 to 17:00 (9 AM to 5 PM)*day (month)Day of month: every day of the month*monthMonth: every month1-5day (week)Day of week: Monday through Friday

On the hour from 09:00 to 17:00, Monday to Friday.

Time zone
Run times, the week view and the snippets use this zone. It starts as your device's zone.
Show times as 9:00 AM instead of 09:00.

Next runs

Each run in your selected time zone, with the same moment in UTC. Daylight saving changes follow cronie, the cron on most Linux servers.
Copy run times (ISO 8601)

Next 7 days

Each square is one hour of local time in your selected zone. Darker squares have more runs. Daylight saving changes are not drawn.

Use it on your platform

Copy-ready config for each scheduler. Dialects differ: some only run in UTC, some can't do seconds, Cloudflare and AWS number weekdays from 1 = Sunday. The snippet handles the conversion and says what changed.
A line for crontab -e on Linux or macOS (Vixie cron, cronie).on.schedule for a workflow, with the timezone field GitHub added in March 2026 (UTC when omitted).A CronJob manifest with the timeZone field (Kubernetes 1.27+).Cron Triggers in wrangler.toml for a Worker. Runs in UTC and numbers weekdays from 1 = Sunday.crons in vercel.json plus the route it calls. Runs in UTC.EventBridge Scheduler (any time zone, recommended by AWS) and a legacy EventBridge scheduled rule (UTC).A .timer unit with OnCalendar=, the systemd replacement for cron.
Runs as writtenRuns in your time zone
crontab -e
Copy crontab -eDownload my-job.crontab
# ┌───────────── minute (0–59)
# │ ┌─────────── hour (0–23)
# │ │ ┌───────── day of month (1–31)
# │ │ │ ┌─────── month (1–12)
# │ │ │ │ ┌───── day of week (0–6, Sunday = 0)
# │ │ │ │ │
# * * * * *  command
CRON_TZ=UTC
0 9-17 * * 1-5  /path/to/my-job.sh >> /var/log/my-job.log 2>&1
  • CRON_TZ=UTC is honored by cronie (Fedora, RHEL, Arch). Other cron daemons ignore it and use the server's time zone, so check timedatectl first.
  • Edit with crontab -e. Cron starts the next run even if the last one is still going; wrap the command in flock -n /tmp/my-job.lock to prevent overlaps.

Need scheduled jobs, queues and monitoring that never miss a run? Talk to our team

Quick answer

The cron expression for every hour during business hours is 0 9-17 * * 1-5. The 0 runs the job on the hour, 9-17 is an inclusive range of hours, and 1-5 limits it to Monday through Friday, so it fires nine times a day from 09:00 to 17:00, 45 times a week. Use 9-16 if the last run should be at 16:00.

  • Live next runs
  • Any time zone
  • Field-by-field breakdown
  • Seven platform snippets
  • Daylight saving aware

How to use this schedule

  1. 1Copy 0 9-17 * * 1-5 with the Copy expression button.
  2. 2Check Next runs in your time zone to confirm it fires when you expect, including around daylight saving changes.
  3. 3Pick your platform under Use it on your platform and copy the ready-made crontab line, workflow, manifest or timer.
  4. 4Need a different time or day? Click Customize to open it in the cron expression generator and change any field.

Why does 9-17 give nine runs, not eight?

Cron ranges are inclusive at both ends, so 9-17 means 9, 10, 11, 12, 13, 14, 15, 16 and 17: nine hours, with a run at 17:00 sharp. Whether that is right depends on what "business hours" means for the job. If the office closes at 17:00 and nothing should happen after closing, end the range at 16.

ExpressionRuns per weekdayLast run
0 9-17 * * 1-5917:00
0 9-16 * * 1-5816:00
30 8-17 * * 1-51017:30
0 8-18/2 * * 1-5618:00

The day-of-week field 1-5 is Monday through Friday, with Sunday as 0 (or 7). In countries with a Sunday-to-Thursday working week, use 0-4 instead.

Whose business hours, and what about holidays?

This is the schedule where the time zone matters most. Cron reads the hours in the server's zone, and servers usually run on UTC. On a UTC server, 0 9-17 * * 1-5 fires from 05:00 to 13:00 in New York during daylight time, which is half a working day early. Fix it at the source: set CRON_TZ if your cron supports it (cronie does), add timezone: next to the cron entry on GitHub Actions, use spec.timeZone on a Kubernetes CronJob, or pick a scheduler with time zone support. Converting the hours to UTC by hand works only until daylight saving time changes the offset. When a team spans several zones, use the zone of the people who act on the job's output.

Cron also knows nothing about public holidays. Rather than editing the crontab every year, let the job exit early when today is in a holiday list:

# at the top of the job script
if grep -qx "$(date +%F)" /etc/company-holidays.txt; then exit 0; fi

For finer granularity in the same window, use */15 9-17 * * 1-5; for a single daily run see every weekday at 9am.

What does each field in 0 9-17 * * 1-5 mean?

FieldValueAllowedMeaning
Minute00–59at minute 0 (on the hour)
Hour9-170–23every hour from 09:00 to 17:00 (9 AM to 5 PM)
Day of month*1–31every day of the month
Month*1–12, JAN–DECevery month
Day of week1-50–7 (0 and 7 are Sunday), SUN–SATMonday through Friday

Read together: On the hour from 09:00 to 17:00, Monday to Friday.

How do I adjust 0 9-17 * * 1-5 to my own schedule?

Small edits to 0 9-17 * * 1-5 cover most real-world needs:

ExpressionWhat it does
0 9-16 * * 1-5Every hour from 09:00 to 16:00 on weekdays, last run before closing
*/15 9-17 * * 1-5Every 15 minutes from 09:00 to 17:45 on weekdays
30 8-17 * * 1-5Every hour at half past, 08:30 to 17:30, Monday to Friday
0 9-17 * * 0-4Every hour from 09:00 to 17:00, Sunday to Thursday
0 8-18/2 * * 1-5Every 2 hours from 08:00 to 18:00 on weekdays

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: Every hour · Every weekday at 9am · Every weekday · Every 15 minutes

Browse all schedules in the cron schedule library.

How do I run 0 9-17 * * 1-5 in crontab, GitHub Actions, Kubernetes and the cloud?

PlatformWrite it asTime zone
Linux crontab0 9-17 * * 1-5Server's time zone; CRON_TZ= in cronie
GitHub Actions- cron: "0 9-17 * * 1-5"UTC by default; add timezone: (IANA name)
Kubernetes CronJobschedule: "0 9-17 * * 1-5"Set timeZone: (1.27+)
Cloudflare Workers0 9-17 * * MON-FRIUTC only; numbers weekdays from 1 = Sunday, so use names
Vercel Cron Jobs0 9-17 * * 1-5UTC only; more than once a day needs Pro (Hobby: once a day)
AWS EventBridge Schedulercron(0 9-17 ? * MON-FRI *)Takes a time zone; legacy scheduled rules are UTC only
systemd timerOnCalendar=Mon..Fri *-*-* 09..17:00:00Add a zone after the time, e.g. Europe/London

In a crontab (crontab -e), the full line looks like this:

0 9-17 * * 1-5  /path/to/job.sh >> /var/log/job.log 2>&1

The 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 9-17 * * 1-5?

  • Ranges are inclusive, so 9-17 includes a run at 17:00. If nothing should happen after closing time, use 9-16.
  • Cron reads the hours in the server's time zone. On a UTC server this schedule runs from 05:00 to 13:00 in New York during daylight time, so set CRON_TZ (cronie), timezone: (GitHub Actions) or spec.timeZone (Kubernetes) to the office's zone.
  • Public holidays are invisible to cron. Exit early from the script when today's date is in a holiday list rather than editing the crontab every year.
  • An asterisk in the minute field (* 9-17 * * 1-5) runs the job every minute of the working day: 540 runs a day instead of 9.
  • On UTC-only platforms (Cloudflare Workers, Vercel, legacy EventBridge rules), the local time this runs at moves by an hour when daylight saving time starts or ends. Use GitHub's timezone:, Kubernetes timeZone, EventBridge Scheduler or cronie's CRON_TZ to pin it to local time.

Frequently asked questions

45 times: nine runs a day (09:00 through 17:00 inclusive) on five weekdays.
End the hour range at 16: 0 9-16 * * 1-5 runs from 09:00 to 16:00, eight times a day. Cron ranges include both ends.
No. Cron only knows the clock and calendar fields. Check a holiday list at the start of your script and exit if today is a holiday.
Cron uses the server time zone by default. Set CRON_TZ in the crontab if your cron supports it, use spec.timeZone on a Kubernetes CronJob, or convert the hours to the server's zone, remembering that the conversion shifts when daylight saving time starts or ends.

Last updated by the Playxoft engineering team.

From the engineers who built this tool

Need scheduled jobs that never miss a run?

Cron is the easy part. Retries, overlapping runs, time zones, queues and alerts when a job silently stops are where schedules break. We build background job systems you can trust, and we will review your setup for free.

More free tools

See all tools

Regex Tester

Test regex live with highlighted matches, plain-English explanations and code export.

Open tool

Cron Expression Generator

New

Build and explain cron schedules, see the next runs in any time zone, copy platform snippets.

Open tool

SQL Formatter

Beautify or minify SQL in 12 dialects, with keyword case, indent and line:column errors.

Open tool

cURL to Python Converter

New

Convert cURL commands into Python requests or httpx code with params, json, files and auth.

Open tool

cURL to Fetch Converter

New

Turn any cURL command into JavaScript fetch() code with headers, JSON, forms and auth.

Open tool

cURL to Axios Converter

New

Convert cURL commands into an Axios request config with params, data, auth and timeouts.

Open tool