Regex and cron

Cron Expression for the First Monday of the Month

At 00:00 on the first Monday of each month, using days 1–7 plus a weekday check. 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 0 1-7 * *
Customize
0minuteMinute: at minute 0 (on the hour)0hourHour: at hour 0 (midnight)1-7day (month)Day of month: days 1 through 7 of the month*monthMonth: every month*day (week)Day of week: every day of the week

At 00:00 on the first Monday of each month, using days 1–7 plus a weekday check.

Standard cron can't say “first Monday” (its two day fields are OR-ed), so this runs on days 1–7 with a weekday check. The run times below apply that check.

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 0 1-7 * *  [ "$(TZ=UTC date +\%u)" = 1 ] && /path/to/my-job.sh >> /var/log/my-job.log 2>&1
  • Cron ORs the two day fields, so 0 0 1-7 * 1 would run on days 1–7 and on every Monday. Instead the job starts on days 1–7 and the check lets only the Monday through.
  • The check sets TZ itself: CRON_TZ only decides when cron starts the job, not the time zone the command sees.
  • Inside a crontab line % starts a new line of input, so it must be escaped as \%.
  • 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

Standard cron can't say "first Monday" directly, so the usual expression is 0 0 1-7 * * with a check in the command that only continues when the day is Monday. The first Monday always falls on days 1 to 7, and the check picks it. Writing 0 0 1-7 * 1 is a trap: cron ORs the two day fields, so it runs on days 1 to 7 and on every Monday. Cloudflare Workers and AWS EventBridge write it as 2#1.

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

How to use this schedule

  1. 1Copy 0 0 1-7 * * 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 doesn't 0 0 1-7 * 1 run on the first Monday?

It looks like it should: days 1 to 7, but only on Mondays. Cron reads it differently. When both the day-of-month and day-of-week fields are restricted, cron runs when either one matches. So 0 0 1-7 * 1 runs on the 1st through the 7th of every month and on every Monday, as many as eleven runs a month instead of one.

The reliable pattern is to let cron pick the candidate days and the command pick the day:

# First Monday of the month at 00:00 (in crontab, % must be escaped as \%)
0 0 1-7 * * [ "$(TZ=Europe/London date +\%u)" = 1 ] && /path/to/job

date +%u prints the ISO weekday, 1 for Monday through 7 for Sunday, so the command only continues on the one Monday that falls in the first seven days. Set TZ to the zone your calendar lives in: CRON_TZ decides when cron starts the job, but the command still sees the server's zone. Change the number to target another weekday, such as 2 for the first Tuesday or 5 for the first Friday.

Which schedulers can say first Monday natively?

Several schedulers extend cron with # (the nth weekday of the month), so no check is needed. Watch the weekday numbers, because they differ:

SchedulerFirst Monday of the month at 00:00
Cloudflare Workers (Sunday is 1)0 0 * * 2#1
AWS EventBridge (Sunday is 1)cron(0 0 ? * 2#1 *)
Quartz (seconds first, Sunday is 1)0 0 0 ? * 2#1
systemd timerOnCalendar=Mon *-*-01..07 00:00:00
Linux crontab, Kubernetes, GitHub Actions, VercelNot supported: use 1-7 plus a weekday check

systemd is the odd one out in a useful way: it ANDs the weekday with the date, so Mon *-*-01..07 means exactly "a Monday in the first week". The same idea covers other ordinals. The second Tuesday is days 8–14 plus a Tuesday check (Tue *-*-08..14 in systemd, 3#2 on Cloudflare), and the last Friday of the month is 6L on Cloudflare and in Quartz. For the plain start of the month, 0 0 1 * * is all you need: see every month.

What does each field in 0 0 1-7 * * mean?

FieldValueAllowedMeaning
Minute00–59at minute 0 (on the hour)
Hour00–23at hour 0 (midnight)
Day of month1-71–31days 1 through 7 of the month
Month*1–12, JAN–DECevery month
Day of week*0–7 (0 and 7 are Sunday), SUN–SATevery day of the week

Read together: At 00:00 on the first Monday of each month, using days 1–7 plus a weekday check.

The day-of-month range 1-7 narrows the candidates to the first week; a weekday check in the command (or # on platforms that support it) picks the Monday.

How do I adjust 0 0 1-7 * * to my own schedule?

Small edits to 0 0 1-7 * * cover most real-world needs:

ExpressionWhat it does
0 9 1-7 * *Days 1–7 at 9 AM; add the Monday check for 9 AM on the first Monday
0 0 8-14 * *Days 8–14, the candidates for the second Monday (with a weekday check)
0 0 1-7 * 1The trap: days 1 to 7 plus every Monday of the month
0 0 * * 2#1First Monday on Cloudflare Workers (not valid in crontab)
0 0 1-3 * *Candidate days for the first working day of the month

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 Monday · Every month · Last day of the month · Every week

Browse all schedules in the cron schedule library.

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

PlatformWrite it asTime zone
Linux crontab0 0 1-7 * * + date checkServer's time zone; CRON_TZ= in cronie
GitHub Actions- cron: "0 0 1-7 * *" + date checkUTC by default; add timezone: (IANA name)
Kubernetes CronJobschedule: "0 0 1-7 * *" + date checkSet timeZone: (1.27+)
Cloudflare Workers0 0 * * 2#1UTC only; supports L and # (Monday is 2)
Vercel Cron Jobs0 0 1-7 * * + date checkUTC only; more than once a day needs Pro (Hobby: once a day)
AWS EventBridge Schedulercron(0 0 ? * 2#1 *)Takes a time zone; legacy scheduled rules are UTC only
systemd timerOnCalendar=Mon *-*-01..07 00:00:00Add a zone after the time, e.g. Europe/London

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

# Set TZ to the zone your calendar runs in; CRON_TZ doesn't reach the command.
0 0 1-7 * *  [ "$(TZ=UTC date +\%u)" = 1 ] && /path/to/job.sh

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 0 1-7 * *?

  • 0 0 1-7 * 1 is not the first Monday: cron combines restricted day fields with OR, so it runs on days 1–7 and on every Monday.
  • In crontab, an unescaped % turns the rest of the line into standard input for the command. Write \% inside date formats or the check breaks.
  • The weekday check uses the server's time zone unless you set TZ for the date command. At 00:00 UTC on a Monday it is still Sunday in the Americas.
  • Weekday numbers differ by platform: date +%u and cron use 1 for Monday, while Cloudflare, AWS EventBridge and Quartz use 2. Day names avoid the guesswork where they are accepted.
  • If either day field starts with * (even */2), Vixie cron and cronie switch to AND, so 0 0 */2 * 1 means odd days that are also Mondays. Other schedulers may still use OR.
  • 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

Standard cron needs two parts: 0 0 1-7 * * to run on days 1 to 7, and a check in the command that today is Monday, such as date +%u printing 1. Cloudflare Workers and AWS EventBridge can write it directly as 2#1 in the weekday field.
Because once both day fields are restricted, cron runs when the day of the month or the day of the week matches. 1-7 in one field and 1 in the other means any of days 1 to 7, plus every Monday.
Schedule days 8 to 14, for example 0 0 8-14 * *, and continue only when the weekday is Tuesday, which date +%u prints as 2. On Cloudflare Workers the same schedule is 0 0 * * 3#2, because Cloudflare counts Sunday as 1.
The first weekday always falls on the 1st, 2nd or 3rd. Schedule 0 0 1-3 * * and continue on the 1st if it is Monday to Friday, or on the 2nd or 3rd only if it is a Monday. Quartz and AWS EventBridge can write this as 1W.

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