Cron schedule
Cron every weekday at 9 AM
The cron expression for every weekday at 9 AM is 0 9 * * 1-5: 09:00 Monday through Friday, five runs a week. It’s the standard schedule for stand-up reminders and morning reports.
| Expression | 0 9 * * 1-5 |
|---|---|
| Runs | 261 times in 2027 |
| systemd OnCalendar | Mon..Fri *-*-* 09:00:00 |
How it works
Three fields carry the meaning: minute 0, hour 9, day of week 1-5. Day of month and month stay *. GitHub’s own documentation uses a close cousin, 30 5 * * 1-5 with timezone: "America/New_York", as its time-zone example.
A 9 AM job is only useful at the recipient’s 9 AM. On UTC-only platforms, 9 AM in São Paulo is 0 12 * * 1-5; 9 AM in New York is 0 13 * * 1-5 in summer and 0 14 * * 1-5 in winter. Near midnight UTC the weekday can shift too: 9 AM Monday in Sydney is Sunday evening UTC.
On Kubernetes set spec.timeZone, on GitHub add timezone, on cronie add CRON_TZ, and the expression stays 0 9 * * 1-5 everywhere.
| Field | Value | Meaning |
|---|---|---|
| Minute | 0 | minute 0 (on the hour) |
| Hour | 9 | hour 9 (9 AM) |
| Day of month | * | every day of the month |
| Month | * | every month |
| Day of week | 1-5 | Monday to Friday |
Next runs
As on GitHub Actions without timezone, Vercel, Cloudflare and Kubernetes with timeZone "Etc/UTC".
| Run | Your time | UTC |
|---|---|---|
| 1 | Calculating… | |
| 2 | ||
| 3 | ||
| 4 | ||
| 5 |
Ready-to-paste versions
The same schedule for each scheduler, with what differs on each one.
crontab (Linux, macOS, BSD)
# m h dom mon dow command
0 9 * * 1-5 /usr/local/bin/job.sh >> /var/log/job.log 2>&1- cron uses the server’s time zone. On cronie (Fedora, RHEL), a
CRON_TZ=Europe/Londonline above the entry changes the zone for the entries below it.
GitHub Actions
on:
schedule:
- cron: '0 9 * * 1-5'
# timezone: 'America/New_York' # optional; UTC when omitted
workflow_dispatch: {}- Runs in UTC unless you set
timezone, and only on the default branch. GitHub’s docs warn that scheduled runs can be delayed at busy times and that schedules in public repositories are disabled after 60 days without activity. - The start of every hour is GitHub’s busiest slot. If the exact minute doesn’t matter, move the
0to something like17to get picked up sooner. - With a
timezonethat observes DST, a time skipped by the spring-forward change advances to the next valid time (the docs’ example: 2:30 AM becomes 3:00 AM).
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: scheduled-job
spec:
schedule: "0 9 * * 1-5"
timeZone: "Etc/UTC"
concurrencyPolicy: Forbid
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: job
image: busybox:1.36
command: ["/bin/sh", "-c", "date; echo running"]spec.timeZoneis stable since Kubernetes 1.27; without it, the kube-controller-manager’s zone applies.concurrencyPolicy: Forbidskips a run while the previous Job is still active.
Vercel Cron Jobs
{
"crons": [
{ "path": "/api/cron", "schedule": "0 9 * * 1-5" }
]
}- Vercel always uses UTC, doesn’t accept names like
MONorJAN, and won’t let you set both day of month and day of week. - This fits the Hobby plan, but Hobby precision is per hour: the invocation can land anywhere within the scheduled hour.
Cloudflare Workers
[triggers]
crons = ["0 9 * * MON-FRI"]- Cron Triggers run on UTC. Changes can take up to 15 minutes to propagate across Cloudflare’s network.
- Cloudflare numbers weekdays 1 = Sunday to 7 = Saturday, unlike standard cron, so the example uses names (
MON,SUN), which are unambiguous.
node-cron (Node.js)
import cron from 'node-cron';
// 6 fields: the first one (seconds) is optional
cron.schedule('0 0 9 * * 1-5', async () => {
await runJob();
}, { timezone: 'UTC', noOverlap: true });- The schedule lives inside the Node process: if it’s down, nothing runs, and three replicas run the job three times.
noOverlapskips a tick while the previous run is still going.
systemd timer
# /etc/systemd/system/job.timer
[Unit]
Description=Run job.service at 09:00 Monday to Friday
[Timer]
OnCalendar=Mon..Fri *-*-* 09:00:00
Persistent=true
[Install]
WantedBy=timers.target
# /etc/systemd/system/job.service
[Service]
Type=oneshot
ExecStart=/usr/local/bin/job.sh
# systemctl daemon-reload && systemctl enable --now job.timer- Check it with
systemd-analyze calendar 'Mon..Fri *-*-* 09:00:00', which prints the normalized form and the next elapse.AccuracySecdefaults to 1min, so the start can drift by up to a minute. Persistent=trueruns the job at boot if the machine was off at the scheduled time, which plain cron doesn’t do.
Spring @Scheduled and Quartz
@Scheduled(cron = "0 0 9 * * 1-5", zone = "UTC")
public void runJob() {
// ...
}
// Quartz CronTrigger:
CronScheduleBuilder.cronSchedule("0 0 9 ? * MON-FRI")- In Spring, the first of the 6 fields is seconds; the rest follow standard cron (0 or 7 = Sunday).
- In Quartz, one of the two day fields must be
?, and weekdays run 1 = Sunday to 7 = Saturday, which is why the example uses names.
Pitfalls
Cloudflare reads 1-5 as Sunday to Thursday
Cloudflare Cron Triggers number weekdays 1 = Sunday to 7 = Saturday. Pasting 0 9 * * 1-5 runs on Sunday through Thursday. Write 0 9 * * MON-FRI there. Quartz has the same numbering.
Converting to UTC can change the day
For zones far from UTC, 09:00 local may fall on the previous or next UTC day. 9 AM Monday in Tokyo is 00:00 Monday UTC, fine; 9 AM Monday in Auckland is Sunday 20:00 or 21:00 UTC, so the UTC weekday range becomes 0-4.
Holidays and time off
A reminder that fires on a public holiday is noise at best. Check a holiday calendar in the job, or accept it and let people mute it.
Frequently asked questions
- What is the cron expression for 9 AM on weekdays?
- 0 9 * * 1-5 runs at 09:00 Monday through Friday.
- How do I run a GitHub Actions workflow at 9 AM on weekdays in my time zone?
- Use cron: '0 9 * * 1-5' with timezone: 'America/New_York' (or your zone). Without timezone the schedule is in UTC.
- How do I run at 9 AM Monday to Friday on Cloudflare Workers?
- crons = ["0 9 * * MON-FRI"], remembering that Cloudflare runs on UTC. 1-5 would mean Sunday to Thursday there.
- How do I run every hour from 9 to 5 on weekdays?
- 0 9-17 * * 1-5 runs on the hour from 09:00 to 17:00, Monday to Friday.
Last reviewed by Arielton Oberek.