Cron Expression Builder

Cron Expression for Monthly on the 1st: 0 0 1 * *

The cron expression 0 0 1 * * runs on the 1st of every month at midnight. Covers @monthly, the last day of month workaround, leap year edge cases, and day 29/30/31 skipping.

100% client-side. Your data never leaves your browser.

Minute
Hour
Day of Month
Month
Day of Week

At 12:00 AM, on day 1 of the month

Next 5 Executions
  • 1.Wed, Jul 1, 2026, 00:00
  • 2.Sat, Aug 1, 2026, 00:00
  • 3.Tue, Sep 1, 2026, 00:00
  • 4.Thu, Oct 1, 2026, 00:00
  • 5.Sun, Nov 1, 2026, 00:00
Quick Reference
*Any value
,List separator
-Range
/Step
1-5Range 1 through 5
*/15Every 15 units

Related Tools

The 0 0 1 * * Expression

The cron expression 0 0 1 * * fires at minute 0, hour 0, on day 1 of every month, regardless of which month or year. This means the job runs at midnight on January 1st, February 1st, March 1st, and so on, exactly 12 times per year (once per calendar month).

Field breakdown:

FieldValueMeaning
Minute0At the top of the hour
Hour0Midnight
Day of month1The 1st of the month
Month*Every month
Day of week*Any day

The @monthly Alias

@monthly is shorthand for 0 0 1 * * and is supported by most cron daemons:

@monthly    /opt/jobs/billing-cycle
# equivalent to:
0 0 1 * *   /opt/jobs/billing-cycle

Unlike some shell aliases, @monthly is interpreted by the cron daemon itself, not by the shell. It has the same effect as the explicit five field form. If you are using Kubernetes CronJobs, AWS scheduled tasks, or GitHub Actions scheduled workflows, check the documentation. Most support @monthly, but a few require the five field syntax.

Edge Cases with Day of Month Values

Months with fewer than 31 days

If you schedule a job for day 29, 30, or 31, it will be silently skipped for months that do not have those days:

ExpressionSkipped months
0 0 29 * *February (most years)
0 0 30 * *February
0 0 31 * *Feb, Apr, Jun, Sep, Nov

This is a significant reliability issue for billing, reporting, and compliance jobs. Use day 1 (0 0 1 * *) if you need the job to fire every single month without exception.

Leap year and February 29th

0 0 29 * * skips February entirely in nonleap years. In leap years, it fires on February 29th, but that only happens every four years (with century year exceptions). Do not use this expression for any job where consistent monthly execution is required.

The Last Day of the Month Problem

Cron has no built in syntax for “the last day of the month.” Some extended implementations (fcron, certain cloud schedulers) support the L operator, but it is nonstandard. The practical workaround is to run the job daily and check the date in the script:

#!/bin/bash
# Exit unless tomorrow is the 1st (i.e., today is the last day of the month)
if [ "$(date -d tomorrow +%d)" != "01" ]; then
  exit 0
fi

# actual job logic here

Crontab entry:

0 23 * * *   /opt/jobs/end-of-month-job

This fires the script every day at 11 PM, but the script itself exits immediately unless it is the last day of the month. It is not elegant, but it is portable and reliable.

The dom and dow OR Logic

When both the day of month field and the day of week field are specified (neither is *), cron uses OR logic, and the job runs when either condition is true:

0 0 1 * 1    # runs on the 1st of the month, AND on every Monday

This is almost never what you want when writing a monthly job. Leaving the day of week field as * (as in 0 0 1 * *) means “any day of week,” so the constraint is purely on the day of month. This is the correct form for a strict “first of the month” schedule.

Real-World Uses for Monthly Cron Jobs

Billing and invoicing

Generating invoices, processing subscription renewals, or recalculating usage based charges typically happens at the billing cycle boundary, the first of the month. Running at midnight on the 1st gives the job a full day before customers see the charge.

Monthly reporting

Finance, sales, and operational reports often roll up the previous month’s data. A job on the 1st ensures the prior month is complete and the data is final before the report runs. Add a small offset (like 0 1 1 * * for 1 AM) to ensure any end of month jobs that ran at midnight have finished.

Data archival

Moving data older than one month to cold storage, archiving old database records to a read only table, or exporting monthly snapshots to object storage are all natural fits for a monthly cron schedule.

Certificate and key rotation

Rotating API keys, refresh tokens, or secrets on a monthly cadence is a common security practice. A first of month cron provides a predictable, auditable rotation schedule.

Verifying the Schedule

from croniter import croniter
from datetime import datetime

cron = croniter("0 0 1 * *", datetime.now())
for _ in range(6):
    print(cron.get_next(datetime))

Output will show the next 6 first of month midnight timestamps. Use this to confirm the schedule fires on the months and times you expect, especially if you are near a month boundary when setting it up.

Timezone Considerations

Like all cron jobs, 0 0 1 * * fires at midnight in the system timezone. If the server runs UTC and your billing cycle closes at midnight US Pacific time, the cron time needs to be adjusted:

If the month boundary happens during a DST transition (which it can, since March 1st often falls near the spring forward date in the US), you need to handle the offset change. Running on UTC and doing timezone math in the application is the more reliable approach for any job where the exact fire time relative to a local timezone matters.