Cron First Day of Month

A cron first day of month schedule puts 1 in the day-of-month field: 0 0 1 * *. Pick a different day or time below, and see how to handle the last day of the month.

Last updated: October 8, 2026

The short answer

The cron first day of month expression is 0 0 1 * *: minute 0, hour 0, day of month 1, any month, any weekday. It runs at midnight on the 1st of every month.

0 0 1 * *
Minute0
Hour0
Day of month1
Month*
Day of week*

Runs at 12:00 AM on day 1 of every month.

Pick the day and the time

Choose the day of the month and the time. "The last day" needs a platform that supports it, and the picker shows the closest Linux option when it does not.

Cron first day of month: 0 0 1 * *

Put the day number in the third field. Every month has a 1st, so this never skips. Change the minute and hour to move the time: 0 2 1 * * is 2:00 AM on the 1st. Because the weekday field is *, it does not matter which weekday the 1st falls on.

Other monthly schedules

A list gives several days, and a list in the month field gives quarters or other patterns.

ExpressionWhat it doesUse
0 2 1 * *Runs at 2:00 AM on day 1 of every month.
The 1st at 2 AM, a quiet hour for billing or reports.
Open
0 9 15 * *Runs at 9:00 AM on day 15 of every month.
The 15th at 9 AM.
Open
0 0 1,15 * *Runs at 12:00 AM on days 1 and 15 of every month.
Twice a month.
Open
0 0 1 */3 *Runs at 12:00 AM on day 1 of every month in January, April, July and October.
Quarterly: January, April, July and October.
Open
0 0 1 1 *Runs at 12:00 AM on day 1 of every month in January.
Once a year, on January 1.
Open
0 0 28 * *Runs at 12:00 AM on day 28 of every month.
The 28th exists in every month.
Open

The last day of the month

The last day varies between 28 and 31, and standard cron has no way to say it. Platforms that add the L character do: Quartz and Spring use 0 0 0 L * ? and EventBridge uses cron(0 0 L * ? *).

On Linux, the standard workaround is to run on the days that could be last and test whether tomorrow is the 1st. CronWave generates this line:

0 0 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && /path/to/command

Runs the command only when tomorrow is the 1st, so it fires once, on the last day. It needs GNU date, and the backslash before the percent sign is required in a crontab.

Days that do not exist in every month

Cron skips a day that is not in the calendar. 0 0 31 * * is not "the last day": Day 31 does not exist in every month, so some months are skipped. So it fires in seven months a year. Use 28 or earlier for a date that must exist in every month, or use the last-day method above.

First weekday or first Monday of the month

Quartz and EventBridge can ask for these directly, for example 0 0 9 1W * ? for the weekday nearest the 1st (Runs at 9:00 AM on the weekday nearest day 1 of every month) or MON#1 for the first Monday. Linux cannot: restricting both the day of month and the day of week runs the job when either matches. The every weekday page explains the trap and the date-check workaround.

First day of the month on each platform

PlatformExpressionNote
Linux / Unix0 0 1 * *@monthly also works. Linux guide
Kubernetes0 0 1 * *@monthly is the same schedule. Kubernetes guide
GitHub Actions0 0 1 * *UTC unless the timezone key is set. GitHub Actions guide
Vercel0 0 1 * *Works on every plan. Remember that the day-of-week field must stay *. Vercel guide
AWS EventBridgecron(0 0 1 * ? *)Needs the ? and a year. AWS guide
Quartz0 0 0 1 * ?Seconds first, and ? in the weekday field. Quartz guide

Month boundaries depend on the time zone

Midnight UTC on the 1st is still the last evening of the previous month in the Americas. If a monthly report must cover a local calendar month, schedule it a few hours after the boundary, or use a platform that lets you set the time zone. The cron timezone converter shows what a UTC schedule means locally.

Sources and further reading