Cron expression for every weekend
The cron expression 0 0 * * 6,0
runs at 12:00 AM, only on Sunday and Saturday. The restricted fields are minute 0, hour 0, and day of week 6,0; the remaining asterisks match anything. That works out to 2 runs per week.
0 0 * * 6,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 | 6,0 | Saturday and 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 * * 6,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 and Saturday": 2 runs per week. The day-of-week field is numbered 0 to 6 with Sunday at 0, so 6,0 selects Sunday and Saturday. Day of month is left as an asterisk, so the calendar date is unrestricted and only the weekday decides.
When to use every weekend
The weekend is the natural window for anything disruptive: heavy maintenance, batch reprocessing that saturates a database, long migrations you would not want competing with live traffic. Two runs a week, both at a time when production is usually quiet. The trade-off is staffing. A job that fails at 00:00 on Saturday can go unnoticed until Monday, so weekend schedules need alerting that actually reaches a human, and the work needs to be safe to re-run once whoever it reaches gets to a keyboard.
Common mistakes with every weekend
The expression trips people twice. Saturday and Sunday sit at opposite ends of a field numbered 0 to 6, so they cannot be written as a range: 6-7 happens to work on some Linux builds, where 7 is accepted as an alias for Sunday, and is rejected elsewhere. Write 6,0 or SAT,SUN. The operational trap is the larger one. Weekend jobs run when nobody is watching, and a maintenance task that fails at 00:00 on Saturday may not be looked at until Monday, by which point both runs of the weekend are gone.
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 * * 6,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 * * 6,0") for more reliable timing.
Kubernetes CronJob
apiVersion: batch/v1
kind: CronJob
metadata:
name: my-cron-job
spec:
schedule: "0 0 * * 6,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.
Vercel Cron
{
"$schema": "https://openapi.vercel.sh/vercel.json",
"crons": [
{
"path": "/api/cron",
"schedule": "0 0 * * 6,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 * * 6,0 /path/to/command
# With logging:
0 0 * * 6,0 /path/to/command >> /var/log/cron.log 2>&1 Variations
-
0 0 * * 0,6At 12:00 AM, only on Sunday and Saturday The identical schedule with the days listed the other way round. Cron sorts the list itself, so the order carries no meaning at all. -
0 0 * * SAT,SUNAt 12:00 AM, only on Saturday and Sunday The same two days by name. This is the form to prefer: it cannot be misread as a range, and it never invites the 6-7 mistake. -
0 3 * * 6,0At 03:00 AM, only on Sunday and Saturday Weekends at 03:00, deep in the quiet window. Buys a heavy migration several more hours of low traffic than a midnight start does. -
0 0 * * 1-5At 12:00 AM, Monday through Friday The inverse — Monday to Friday. Weekdays can be written as a range because they are contiguous in the field; the weekend cannot.
Frequently asked questions
How do I read the cron expression 0 0 * * 6,0?
Read the five space-separated fields left to right as minute, hour, day of month, month, and day of week. In 0 0 * * 6,0 the minute is 0, hour is 0, day of month is *, month is *, day of week is 6,0. Of the operators cron defines, this expression uses only the ones that matter here: an asterisk matches every value in its field and a comma builds a list of individual values. Put together, cronstrue reads the whole thing as "At 12:00 AM, only on Sunday and Saturday", and a scheduler that checks all five fields once a minute will start the job 2 runs per week.
What timezone does 0 0 * * 6,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 and Saturday run at 00:00 UTC happens at 19:00 on Saturday and Friday 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.
Why is the weekend written as 6,0 instead of 6-7?
The day-of-week field is numbered 0 to 6 with Sunday at 0, so Saturday and Sunday sit at opposite ends of the range and cannot be expressed as a contiguous span. Writing 6,0 lists both days explicitly, and 0,6 is the same schedule. Many implementations also accept 7 as an alias for Sunday, which makes 6-7 work on Linux — but it is not portable, and some parsers reject it. Stick to the list form, or use the three-letter names SAT,SUN, which every mainstream scheduler reads without ambiguity.
Related cron schedules
-
0 0 * * 1Every Monday -
0 0 * * 5Every Friday -
0 0 * * 1-5Every weekday -
0 0 * * 0Every week -
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.