Developer guide

Cron Every 2 Weeks: Biweekly Cron Expressions, Explained

Cron has no native “every other week” field, which is why biweekly jobs confuse everyone at least once. The trick is day-of-month arithmetic: pick a day range that only occurs in one week out of two and combine it with the weekday you want. This guide shows the exact expressions for every common fortnightly schedule and the traps that silently break them.

Benjamin Rotshtein

Written by Benjamin Rotshtein

Updated

How do I run a cron job every 2 weeks?

Combine a day-of-month window with the weekday you want: 0 0 1-7,15-21 * 1 runs every 2 weeks on Monday at midnight. Cron has no week-parity field, so the 1-7 and 15-21 windows force the job to fire in one week out of two, then skip the next — a true biweekly cadence.

How do I run a cron job every 2 weeks?
Combine a day-of-month window with the weekday: every 2 weeks on Monday is 0 0 1-7,15-21 * 1.
Why can't cron just say “every 2 weeks”?
The 5-field format has no week-parity concept, so a fortnightly interval must be faked with day-of-month ranges.
Is 0 0 * * 1 the same as every other Monday?
No — that is every Monday of every week. You need the day-of-month constraint to force the one-week gap.

Why “every 2 weeks” is not a native cron concept

The five cron fields — minute, hour, day-of-month, month, day-of-week — describe points in time, not intervals counted from a starting date. There is no “every N weeks” because weeks don't exist as a field. The standard workaround constrains day-of-month so it only matches during one week of every fortnight.

The day-of-month window trick

Think in two-week halves of the month. Days 1–7 are week one, days 8–14 week two, 15–21 week three, and so on. If you want a job on Mondays only every other week, allow day-of-month 1–7 or 15–21 (both are “first” weeks of their half), combined with the weekday field pinned to Monday:

#  minute  hour  day-of-month  month  day-of-week
     0      0     1-7,15-21       *        1     # every 2 weeks, Monday

Monday always lands on either day-of-month 1–7 (first week) or 15–21 (third week), and never on 8–14 or 22–28. So the expression fires on Monday of week one and week three, skips week two and week four — a clean biweekly cadence. The same windows work for any weekday; just change the last field.

Verified biweekly expressions

ExpressionMeaningTypical use
0 0 1-7,15-21 * 1Every 2 weeks on Monday at midnightClassic fortnightly
0 0 1-7,15-21 * 5Every 2 weeks on Friday at midnightPayroll / reports
0 9 8-14,22-28 * 3Every 2 weeks on Wednesday at 9 AMBusiness hours
30 4 1-7,15-21 * 0Every 2 weeks on Sunday at 4:30 AMMaintenance window
0 0 1-7,15-21 * *Every 2 weeks on the 1st day that falls in the windowAny weekday

A free-text day-of-month without a weekday (like 0 0 1-7,15-21 * *) runs on every day inside the windows — that is daily bursts twice a month, not once a fortnight, so only use it if that is genuinely what you want.

The traps that break biweekly cron

  • Weekday without a window: 0 0 * * 1 is weekly, not biweekly — the most common mistake.
  • Day-of-month plus weekday confusion: in standard cron, when both day-of-month and day-of-week are specified, the job runs if either matches (OR logic), unlike some quartz schedulers. With 1-7,15-21 plus a weekday, the OR still yields the biweekly pattern because the weekday only occurs inside those windows.
  • Short and long months: months with 28, 29 or 30 days shift where the windows land. Day 28 is always in week four, so a 22-28 window stays valid every month — prefer it over fixed dates near month end.
  • DST: a 2 AM job on a spring-forward Sunday simply does not run that day. See the cron time and DST guide for handling.

Cleaner alternatives for real systems

If you control the scheduler rather than a raw crontab, skip the trickery:

# Python APScheduler
from apscheduler.schedulers.background import BackgroundScheduler
from apscheduler.triggers.cron import CronTrigger
scheduler = BackgroundScheduler()
scheduler.add_job(my_job, CronTrigger(day_of_week="mon", day="1-7,15-21"))
# or, clearer — a wrapper that skips odd weeks:
scheduler.add_job(my_job, CronTrigger(day_of_week="mon"))  # weekly trigger,
                                                           # guard inside my_job

A plain weekly trigger plus an internal week-parity guard (check a marker file or datetime.now().isocalendar()[1] % 2) is the most readable biweekly implementation and survives month boundaries exactly.

Generate a valid expression

For the cadences cron handles natively — every minute and up — the Cron Generator turns plain English into a correct 5-field expression and previews the next runs.

Frequently asked questions

How do I schedule a cron job every 2 weeks?

Use a day-of-month expression that only matches one week out of two, combined with the target weekday. Every 2 weeks on Monday is: 0 0 1-7,15-21 * 1. Monday falls on day-of-month 1-7 in one week of the month and 15-21 in the next, so the job runs exactly once per fortnight.

Why is there no 'every 2 weeks' field in cron?

The 5-field format has no concept of week parity. The only fields are minute, hour, day-of-month, month and day-of-week, so a pure biweekly interval must be expressed through day-of-month arithmetic rather than an interval count.

Can I just write 0 0 * * 1 to mean every other Monday?

No. That expression means every Monday of every week. To get every other Monday you must constrain day-of-month so only one of the two weeks matches, for example 0 0 1-7,15-21 * 1.

What about every 2 weeks on Friday?

Use 0 0 1-7,15-21 * 5. The day-of-week 5 (Friday) combined with day-of-month 1-7 or 15-21 guarantees Friday falls in the chosen fortnight window once, then not again for a full week, giving you a true biweekly cadence.

Is there a cleaner alternative to day-of-month expressions?

Yes. Many people prefer a wrapper script that tracks a marker file or timestamp and skips every other week, keeping a plain weekly cron line (0 0 * * 1) as the trigger. For application schedulers, APScheduler, croniter or a language scheduler with calendar arithmetic are far more readable than day-of-month tricks.

Does the biweekly window work on a 31-day month?

Yes. Windows like 1-7,15-21 always exist in every month, and the weekday you combine with them still lands inside one of them exactly once per fortnight. Avoid windows ending near day 28 (for example 22-28) for months with fewer days, and prefer windows that never cross into the next month.

Related guides