Run on the 1st and 15th of Every Month | CronBase
0 0 1,15 * * At midnight on the first and fifteenth day of every month
The `0 0 1,15 * *` cron expression schedules a task to execute at exactly midnight (12:00 AM) on the first and fifteenth days of every month. This semi-monthly cadence is commonly used for processing payroll, generating bi-weekly financial statements, executing recurring billing cycles, and performing mid-month data archival tasks.
- Minute
- 0
- Hour
- 0
- Day of Month
- 1,15
- Month
- *
- Day of Week
- *
Next 5 Runs
- in 3d 13h
- in 19d 13h
- in 33d 13h
- in 50d 13h
- in 64d 13h
* Tools
Code & Implementations
const cron = require('node-cron');
const { exec } = require('child_process');
// Schedule task to run on the 1st and 15th of the month at midnight UTC
cron.schedule('0 0 1,15 * *', () => {
console.log('Starting semi-monthly processing job...');
exec('/usr/local/bin/process-payroll.sh', (error, stdout, stderr) => {
if (error) {
console.error(`Execution error: ${error.message}`);
return;
}
if (stderr) {
console.warn(`Warnings: ${stderr}`);
}
console.log(`Output: ${stdout}`);
});
}, {
scheduled: true,
timezone: \"UTC\"
}); › Setup notes
Install node-cron package via npm, then run this script as a background daemon process using PM2 or systemd.
# Add this line to your crontab using the 'crontab -e' command\n0 0 1,15 * * /usr/local/bin/run-biweekly-billing.sh >> /var/log/billing.log 2>&1 › Setup notes
Open your user crontab editor using bash, paste this line at the bottom, and ensure the target execution script is marked as executable.
from apscheduler.schedulers.blocking import BlockingScheduler
import logging
import subprocess
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
def run_biweekly_task():
logger.info(\"Executing scheduled bi-weekly task\")
try:
result = subprocess.run([\"/usr/local/bin/backup-db.sh\"], capture_output=True, text=True, check=True)
logger.info(f\"Task completed: {result.stdout}\")
except subprocess.CalledProcessError as e:
logger.error(f\"Task failed with error: {e.stderr}\")
scheduler = BlockingScheduler(timezone=\"UTC\")
# Trigger on the 1st and 15th day of every month at midnight
scheduler.add_job(run_biweekly_task, 'cron', day='1,15', hour=0, minute=0)
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
pass › Setup notes
Install the apscheduler library using pip, then execute this script to begin the scheduling loop.
package main
import (
\"fmt\"
\"log\"
\"os/exec\"
\"time\"
\"github.com/robfig/cron/v3\"
)
func main() {
// Use UTC to avoid DST complications
nyc, err := time.LoadLocation(\"UTC\")
if err != nil {
log.Fatalf(\"Failed to load timezone: %v\", err)
}
c := cron.New(cron.WithLocation(nyc))
_, err = c.AddFunc(\"0 0 1,15 * *\", func() {
log.Println(\"Starting semi-monthly database cleanup...\")
cmd := exec.Command(\"/usr/local/bin/cleanup.sh\")
out, err := cmd.CombinedOutput()
if err != nil {
log.Printf(\"Execution failed: %v, Output: %s\", err, string(out))
return
}
log.Printf(\"Execution succeeded: %s\", string(out))
})
if err != nil {
log.Fatalf(\"Failed to schedule cron job: %v\", err)
}
c.Start()
select {}
} › Setup notes
Initialize a Go module, import the robfig/cron/v3 package, and run the main function to handle scheduling natively.
package com.example.cron;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class SemiMonthlyScheduler {
private static final Logger logger = LoggerFactory.getLogger(SemiMonthlyScheduler.class);
// Standard Spring cron: second, minute, hour, day-of-month, month, day-of-week
@Scheduled(cron = \"0 0 0 1,15 *\", zone = \"UTC\")
public void executeSemiMonthlyJob() {
logger.info(\"Starting scheduled semi-monthly ledger reconciliation...\");
try {
// Business logic goes here
logger.info(\"Ledger reconciliation completed successfully.\");
} catch (Exception e) {
logger.error(\"Error executing ledger reconciliation: \", e);
}
}
} › Setup notes
Enable scheduling in your Spring Boot main application class using @EnableScheduling, then add this component to your codebase.
apiVersion: batch/v1
kind: CronJob
metadata:
name: semi-monthly-billing-job
namespace: default
spec:
schedule: \"0 0 1,15 * *\"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: billing-executor
image: billing-service:latest
command: [\"/bin/sh\", \"-c\", \"/app/run-billing.sh\"]
restartPolicy: OnFailure › Setup notes
Save this manifest to a YAML file and apply it using 'kubectl apply -f manifest.yaml' to provision the CronJob in your cluster.
Monitor this schedule in production
Get alerted the moment this cron job fails, is late, or doesn't run. BetterStack tracks execution, duration, and output — no infrastructure required.
Platform Equivalents
AWS EventBridge
Standard cron expressions often need conversion for AWS EventBridge schedules.
cron(0 0 1,15 * ? *) Systemd Timer
OnCalendar*-*-01,15 00:00:00
[Unit]
Description=Timer for cron expression: 0 0 1,15 * *
[Timer]
OnCalendar=*-*-01,15 00:00:00
Persistent=true
[Install]
WantedBy=timers.target
Frequently Asked Questions
How can I handle timezone changes for a twice-monthly cron job?
To prevent Daylight Saving Time (DST) shifts from causing duplicate runs or missed executions, configure your cron runner or host server to operate entirely in UTC. This ensures execution occurs at the exact same physical interval regardless of seasonal clock changes.
What happens if the server is offline during the scheduled execution time?
Standard cron does not catch up on missed executions. If your server is offline at midnight on the 1st or 15th, the job will not run until the next scheduled date. For critical tasks, use a tool like anacron or implement a startup check that detects missed runs.
How can I test this cron schedule without waiting for the 1st or 15th?
You can simulate the execution by temporarily modifying the cron expression to run in the next few minutes (e.g., `*/5 * * * *`) or by manually triggering the underlying script or Kubernetes CronJob using `kubectl create job --from=cronjob/my-job`.
Can I schedule this job to run only on weekdays if the 1st or 15th falls on a weekend?
Standard cron cannot natively combine day-of-month and day-of-week with an 'AND' condition; it treats them as 'OR'. To achieve this, you must run the cron job on the 1st and 15th, and then use an inline shell script check like `[ $(date +%u) -le 5 ]` to exit early on weekends.
Why is running a resource-heavy database backup at midnight on these days risky?
Midnight is a highly contested slot where many default system maintenance tasks, log rotations, and automated backups trigger simultaneously. This causes resource contention. Shifting your schedule to an off-peak time like 02:15 AM reduces CPU and disk I/O bottlenecks.
* Explore
Related expressions you might need
Last verified: