Cron expression for every week
The cron expression 0 0 * * 0
runs at 12:00 AM, only on Sunday. The restricted fields are minute 0, hour 0, and day of week 0; the remaining asterisks match anything. That works out to one run per week.
0 0 * * 0 Field breakdown
| Field | Value | Meaning |
|---|---|---|
| Minute | 0 | The top of the hour (:00) |
| Hour | 0 | 00:00 (midnight) |
| Day of month | * | Every day of the month (1–31) |
| Month | * | Every month (1–12) |
| Day of week | 0 | Sunday |
Next runs
- —
- —
- —
- —
- —
Run times are calculated in your browser timezone. The scheduler that executes the job uses its own — always UTC on Vercel Cron, UTC by default on GitHub Actions, the host clock on crontab.
How this schedule works
Cron evaluates the five fields of 0 0 * * 0 — minute, hour, day of month, month, day of week — against the clock once a minute and starts the job on any minute where all five match, which cronstrue reads as "At 12:00 AM, only on Sunday": one run per week. The day-of-week field is numbered 0 to 6 with Sunday at 0, so 0 selects Sunday. Day of month is left as an asterisk, so the calendar date is unrestricted and only the weekday decides.
When to use every week
A weekly run fits digests, rollups, rotating backups at the week boundary, and exports to an analytics warehouse where daily granularity is more than anyone needs. Sunday at 00:00 puts the run at the conventional start of the week, so the seven days it summarizes are the seven that just finished. With only 52 runs a year, each one carries weight: a single silent failure loses a week of output, which makes alerting and a documented manual re-run path far more important here than on a schedule that comes round again in five minutes.
Common mistakes with every week
A weekly schedule gets 52 chances a year to be right, which makes every mistake slow to surface and expensive when it does. The common one is the day. Cron's week starts at Sunday 0, so 0 0 * * 0 is Sunday and 0 0 * * 1 is Monday, and a report labelled weekly can be summarising a window that begins a day away from where the business thinks the week begins. The second is silence: a job that has not run for eight days is broken, but nothing in cron will say so. Alert on the absence of a successful run, not only on errors.
Platform snippets
The same expression, ready to paste into the four schedulers that read five-field cron. The notes below each snippet are the ones that follow from this schedule; the cron expression generator lists every caveat for every platform.
GitHub Actions
name: Scheduled workflow
on:
schedule:
- cron: '0 0 * * 0'
workflow_dispatch:
jobs:
scheduled:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run job
run: echo "Running scheduled job" - • Workflows scheduled at the top of the hour may be delayed during high-load periods. Consider offsetting the minute field (e.g. "5 0 * * 0") for more reliable timing.
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: my-cron-job
spec:
schedule: "0 0 * * 0"
jobTemplate:
spec:
template:
spec:
containers:
- name: job
image: my-image:latest
command: ["/bin/sh", "-c", "echo Running"]
restartPolicy: OnFailure - • Do NOT use CRON_TZ or TZ inside the schedule string. Kubernetes 1.29+ rejects this at creation with a validation error; earlier versions issue a warning. Existing CronJobs using TZ/CRON_TZ will continue to warn on update. Use the timeZone field instead.
- • Kubernetes supports shorthand macros: @yearly, @monthly, @weekly, @daily, @hourly.
Vercel Cron
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"crons": [
{
"path": "/api/cron",
"schedule": "0 0 * * 0"
}
]
} - • Hobby plan: invocations occur within the specified hour (e.g. "0 8 * * *" runs between 08:00:00 and 08:59:59).
crontab
# Edit your crontab: crontab -e
0 0 * * 0 /path/to/command
# With logging:
0 0 * * 0 /path/to/command >> /var/log/cron.log 2>&1 - • Most modern implementations (vixie-cron, cronie) support shorthand macros: @yearly, @monthly, @weekly, @daily, @hourly, @reboot. These are not defined by POSIX — check your platform.
Variations
-
0 0 * * 1At 12:00 AM, only on Monday Weekly on Monday instead of Sunday. Which of the two is right depends entirely on where the business thinks the week begins. -
0 9 * * 1At 09:00 AM, only on Monday Monday at 09:00. A weekly job that fails at midnight on Sunday can sit broken for seven days; this one fails while someone is watching. -
0 0 * * SUNAt 12:00 AM, only on Sunday The same schedule with the day named. SUN is unambiguous; 0 relies on the reader knowing that cron's week starts on Sunday. -
0 0 * * 0,3At 12:00 AM, only on Sunday and Wednesday Sunday and Wednesday — twice a week, splitting the seven-day gap roughly in half without doubling the cost of a daily job.
Frequently asked questions
How do I read the cron expression 0 0 * * 0?
Read the five space-separated fields left to right as minute, hour, day of month, month, and day of week. In 0 0 * * 0 the minute is 0, hour is 0, day of month is *, month is *, day of week is 0. Of the operators cron defines, this expression uses only the ones that matter here: an asterisk matches every value in its field. Put together, cronstrue reads the whole thing as "At 12:00 AM, only on Sunday", and a scheduler that checks all five fields once a minute will start the job one run per week.
What timezone does 0 0 * * 0 run in?
The expression carries no timezone of its own: it names hour 0, and the scheduler decides which hour 0 that is. Read as UTC, the run lands at 00:00 — 19:00 the previous day in New York, 00:00 in London, and 09:00 in Tokyo on a January date, with daylight saving moving the first two later in the year, so the same UTC instant is 20:00 the previous day in New York in July. That offset crosses a calendar day, and this schedule is pinned to a weekday, so the local weekday moves with it: the Sunday run at 00:00 UTC happens at 19:00 on Saturday in New York. A job that reads the weekday back from the local clock there will disagree with the expression that scheduled it. Set the zone rather than converting by hand where you can: GitHub Actions defaults to UTC but takes an optional timezone key beside cron, and a Kubernetes CronJob has spec.timeZone, stable since 1.27. Where you cannot, convert deliberately: Vercel Cron is UTC-only, and a Linux crontab follows the host clock unless CRON_TZ overrides it.
Does cron support @weekly instead of a five-field expression?
Most Linux implementations, including vixie-cron and cronie, accept the shorthand macros @yearly, @monthly, @weekly, @daily, @hourly, and @reboot, and Kubernetes CronJobs accept them too. @weekly is defined as 0 0 * * 0 — midnight on Sunday. The macros are not part of POSIX, GitHub Actions rejects them outright, and @reboot has no meaning in a hosted scheduler. Writing the five-field expression is the portable choice: it survives a move between platforms, and it states the exact day and hour instead of relying on each implementation to agree on what "weekly" means.
Related cron schedules
-
0 0 * * 1Every Monday -
0 0 * * 5Every Friday -
0 0 * * 1-5Every weekday -
0 0 * * 6,0Every weekend -
0 0 1 * *Every month -
0 0 1 */3 *Every quarter
Build a custom schedule in the cron expression generator, or browse every epochkit tool.