Run Yearly Jobs on January 1st | CronBase
0 0 1 1 * At midnight on the first day of January every year
This standard cron expression schedules a task to run exactly once a year at midnight on January first. It is commonly utilized for annual system tasks such as generating year-end financial ledgers, archiving historical database records to cold storage, resetting yearly usage quotas, and executing major compliance audits across enterprise systems.
- Minute
- 0
- Hour
- 0
- Day of Month
- 1
- Month
- 1
- Day of Week
- *
Next 5 Runs
- in 159d 3h
- in 524d 3h
- in 890d 3h
- in 1255d 3h
- in 1620d 3h
* Tools
Code & Implementations
#!/usr/bin/env bash
set -euo pipefail
# Securely append the annual cron job to the user's crontab
CRON_JOB="0 0 1 1 * /usr/local/bin/annual-archive.sh >> /var/log/cron-annual.log 2>&1"
(crontab -l 2>/dev/null | grep -F -q "$CRON_JOB") || (
(crontab -l 2>/dev/null; echo "$CRON_JOB") | crontab -
echo "Successfully scheduled annual job in crontab."
) › Setup notes
Save this script as setup-cron.sh, make it executable with chmod +x, and run it to register the annual task in the current user's crontab.
const cron = require('node-cron');
const { execYearlyArchival } = require('./tasks/archive');
// Schedule task for January 1st at midnight (00:00)
cron.schedule('0 0 1 1 *', async () => {
console.log('Starting annual maintenance and archival process...');
try {
await execYearlyArchival();
console.log('Annual archival completed successfully.');
} catch (error) {
console.error('CRITICAL: Annual archival failed:', error);
// Trigger external alerting system (e.g., PagerDuty, Slack webhook)
}
}, {
timezone: "UTC"
}); › Setup notes
Install node-cron using npm install node-cron, and run this script as a long-running background process using a process manager like PM2.
from apscheduler.schedulers.blocking import BlockingScheduler
import logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('annual_job')
def run_annual_job():
logger.info("Starting annual year-end financial processing...")
try:
# Place your business logic here
logger.info("Annual processing completed successfully.")
except Exception as e:
logger.critical(f"Annual job failed: {str(e)}", exc_info=True)
scheduler = BlockingScheduler(timezone="UTC")
# Run on month 1, day 1, hour 0, minute 0
scheduler.add_job(run_annual_job, 'cron', month=1, day=1, hour=0, minute=0)
if __name__ == '__main__':
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
pass › Setup notes
Install APScheduler via pip install apscheduler, and execute this script. It runs as a blocking process waiting for the annual execution trigger.
package main
import (
"log"
"os"
"time"
"github.com/robfig/cron/v3"
)
func main() {
utc, err := time.LoadLocation("UTC")
if err != nil {
log.Fatalf("Failed to load UTC timezone: %v", err)
}
c := cron.New(cron.WithLocation(utc))
_, err = c.AddFunc("0 0 1 1 *", func() {
log.Println("Executing annual system maintenance...")
if err := performAnnualReset(); err != nil {
log.Printf("CRITICAL: Annual reset failed: %v", err)
}
})
if err != nil {
log.Fatalf("Error scheduling cron job: %v", err)
}
c.Start()
select {} // Block forever
}
func performAnnualReset() error {
// Business logic goes here
return nil
} › Setup notes
Initialize a Go module, run go get github.com/robfig/cron/v3, and run the main.go file in your production environment.
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 AnnualMaintenanceScheduler {
private static final Logger logger = LoggerFactory.getLogger(AnnualMaintenanceScheduler.class);
// Runs at 00:00 on January 1st every year
@Scheduled(cron = "0 0 1 1 *", zone = "UTC")
public void runAnnualTasks() {
logger.info("Initiating annual database purging and reporting...");
try {
executePurge();
logger.info("Annual tasks completed successfully.");
} catch (Exception e) {
logger.error("CRITICAL: Annual task execution failed", e);
}
}
private void executePurge() throws Exception {
// Enterprise database purge logic here
}
} › Setup notes
Ensure @EnableScheduling is declared on your Spring Boot main application class, and include this Component in your application package scan.
apiVersion: batch/v1
kind: CronJob
metadata:
name: annual-data-archiver
namespace: production
spec:
schedule: "0 0 1 1 *"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 5
jobTemplate:
spec:
template:
spec:
containers:
- name: archiver
image: registry.example.com/jobs/archiver:v1.2.0
env:
- name: TZ
value: "UTC"
restartPolicy: OnFailure › Setup notes
Apply this manifest using kubectl apply -f cronjob.yaml. The job uses a strict concurrency policy to prevent overlapping runs.
Last verified:
Keep this cron job monitored 24/7
UptimeRobot alerts you the moment a scheduled job stops responding. Free plan monitors up to 50 endpoints — no credit card required.
Platform Equivalents
AWS EventBridge
Standard cron expressions often need conversion for AWS EventBridge schedules.
cron(0 0 1 1 ? *) Systemd Timer
OnCalendar*-01-01 00:00:00
[Unit]
Description=Timer for cron expression: 0 0 1 1 *
[Timer]
OnCalendar=*-01-01 00:00:00
Persistent=true
[Install]
WantedBy=timers.target
Last verified:
Frequently Asked Questions
How do I test an annual cron job without waiting a full year?
You should design your application logic to be decoupled from the cron scheduler. Expose a secure, authenticated REST endpoint, CLI command, or invoke the execution function directly in a staging environment with mock data to verify behavior.
What happens to the job if a leap second occurs on December 31st?
Standard operating systems and modern NTP servers resolve leap seconds via 'slewing' (gradually adjusting the clock speed). The cron daemon relies on system time, so it will execute normally at midnight without missing the trigger.
How do I handle timezone transitions like Daylight Saving Time for this job?
Always run your cron daemon and schedule your annual jobs in UTC. Running in local timezones can cause the job to run twice or be skipped entirely if the local midnight transition coincides with a DST shift.
What is the best way to monitor a job that runs so infrequently?
Traditional passive monitoring (alerting on failure) is insufficient. Use a 'dead-man's switch' service (like Healthchecks.io or Opsgenie) that expects a ping within a specific window on January 1st and alerts if the ping is missed.
Can I use the @yearly shortcut instead of 0 0 1 1 *?
Yes, in standard Vixie cron and dialects like Kubernetes or Go's robfig/cron, @yearly and @annually are exact equivalents to 0 0 1 1 * and can be used to improve readability.
* Explore
Related expressions you might need
Last verified: