Run at 5 AM and 5 PM Weekdays | CronBase
15 5 * * 1-5 At 5:15 AM and 5:15 PM, Monday through Friday
* In a Nutshell
The cron expression 15 5 * * 1-5 runs At 5:15 AM and 5:15 PM, Monday through Friday. Executing tasks at both the start and end of the business day is crucial for maintaining application health and data consistency. This cadence ensures that critical processes, like overnight batch job wrap-ups and morning data refreshes, are completed before the workday begins, and that end-of-day reporting or archiving can commence promptly. This prevents data staleness and operational backlogs.
* When to use this
Use 15 5 * * 1-5 when a recurring task needs to run At 5:15 AM and 5:15 PM, Monday through Friday. This schedule is commonly associated with business hours schedules and report generation and weekday schedules workloads. It uses Standard (5-Field POSIX) syntax, supported by Unix cron daemons, cloud schedulers such as AWS EventBridge, and container orchestration platforms such as Kubernetes CronJob.
CronBase parses 15 5 * * 1-5 using a dialect-aware rules engine that identifies the Standard (5-Field POSIX) format, validates field structure against the Standard (5-Field POSIX) specification, and produces the translation above. Next run times are calculated by forward-scanning from the current UTC clock. Learn how CronBase works.
Platform Implementations
Bash
Prerequisites
Unix/Linux host with a cron daemon running (vixie-cron, cronie, or systemd-cron). The script at /usr/local/bin/run-task.sh must exist and be executable (chmod +x).
Configuration
Run crontab -e to open the crontab editor. Cron reads the server's local timezone; prefix with CRON_TZ=UTC before the expression to pin to UTC. Always redirect output with >> /var/log/cron-tasks.log 2>&1 to capture both stdout and stderr.
Gotchas
Cron jobs inherit a minimal PATH — use full binary paths or set PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin at the top of the crontab. For sub-hourly schedules, add flock -n /tmp/run-task.lock before the command to skip overlapping runs if the previous execution is still running.
# Add to crontab with: crontab -e
15 5 * * 1-5 /usr/local/bin/run-task.sh >> /var/log/cron-tasks.log 2>&1 Last verified:
Nodejs
Prerequisites
Node.js 18+ with node-cron installed (npm install node-cron). Add "type": "module" to package.json to use the import syntax shown above.
Configuration
Pass { timezone: 'UTC' } as the third argument to cron.schedule(). Without this option the schedule uses the Node.js process timezone, which shifts during DST transitions when servers are not pinned to UTC.
Gotchas
node-cron uses standard 5-field cron syntax — not Quartz 6-field. If your job runs longer than the schedule interval the next trigger fires while the previous is still executing. Use a boolean guard or a queue to skip concurrent runs rather than relying on the scheduler to enforce it.
import cron from 'node-cron';
cron.schedule('15 5 * * 1-5', async () => {
console.log('[cron] running at', new Date().toISOString());
// your task logic here
}, { timezone: 'UTC' }); Last verified:
Python
Prerequisites
Python 3.8+ with apscheduler installed (pip install apscheduler). For Python 3.12+ use apscheduler>=3.10.
Configuration
CronTrigger.from_crontab() accepts a standard 5-field cron string. Always pass timezone='UTC' to both the BlockingScheduler constructor and the trigger to ensure consistent scheduling regardless of the server's locale.
Gotchas
BlockingScheduler.start() blocks the calling thread indefinitely. For a web application, use BackgroundScheduler instead and call scheduler.start() at application startup. APScheduler logs missed fires if the process is stopped and restarted — configure misfire_grace_time (in seconds) to control how late a missed job is allowed to run.
from apscheduler.schedulers.blocking import BlockingScheduler
from apscheduler.triggers.cron import CronTrigger
scheduler = BlockingScheduler(timezone='UTC')
@scheduler.scheduled_job(
CronTrigger.from_crontab('15 5 * * 1-5', timezone='UTC')
)
def run_task() -> None:
print('task running')
# your task logic here
scheduler.start() Last verified:
Golang
Prerequisites
Go 1.18+ and github.com/robfig/cron/v3 (go get github.com/robfig/cron/v3).
Configuration
Always create the scheduler with cron.New(cron.WithLocation(time.UTC)). Without WithLocation, the library defaults to the server's local timezone. Call c.Start() to begin the scheduler, then block with select {} to keep the process alive.
Gotchas
robfig/cron v3 uses standard 5-field cron expressions by default. To add second-level precision (6 fields), pass cron.WithSeconds() to cron.New() — but this changes field positions, so never mix syntaxes in the same scheduler. Always check the error returned by c.AddFunc() — a malformed expression is silently ignored without it.
package main
import (
"fmt"
"time"
"github.com/robfig/cron/v3"
)
func main() {
c := cron.New(cron.WithLocation(time.UTC))
_, err := c.AddFunc("15 5 * * 1-5", func() {
fmt.Println("task running at", time.Now().UTC())
// your task logic here
})
if err != nil {
panic(err)
}
c.Start()
defer c.Stop()
select {}
} Last verified:
Java
Prerequisites
Spring Boot 2.7+ (or Spring Framework 5.3+) with spring-context on the classpath. Annotate your @SpringBootApplication class with @EnableScheduling — without it, @Scheduled methods are silently ignored.
Configuration
Spring @Scheduled uses a 6-field Quartz-style expression: [sec] [min] [hr] [dom] [mon] [dow]. The expression 0 15 5 ? * 1-5 is derived from 15 5 * * 1-5 — a leading 0 is prepended for the seconds field, and ? replaces the unconstrained day field.
Gotchas
Standard Unix cron has 5 fields; Spring requires 6. Pasting a 5-field expression directly into @Scheduled shifts every field by one and the job misfires silently. Use ? for either dom or dow — Quartz does not allow both to be *.
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@Component
public class ScheduledTask {
@Scheduled(cron = "0 15 5 ? * 1-5")
public void runTask() {
System.out.println("task running at: " + java.time.Instant.now());
// your task logic here
}
} Last verified:
Kubernetes
Prerequisites
Kubernetes 1.21+ (CronJob API is GA). kubectl configured with cluster access. Container image must be pullable from within the cluster.
Configuration
Apply with kubectl apply -f cronjob.yaml. Check status with kubectl get cronjobs and inspect run history with kubectl get jobs. concurrencyPolicy: Allow is set because this schedule fires infrequently — parallel runs are acceptable.
Gotchas
Without startingDeadlineSeconds, a missed job (e.g., due to cluster downtime) triggers as soon as the controller recovers. Kubernetes 1.25+ supports timeZone: UTC in the spec to avoid timezone ambiguity. Keep successfulJobsHistoryLimit and failedJobsHistoryLimit low to avoid accumulating stale Job objects in the cluster.
apiVersion: batch/v1
kind: CronJob
metadata:
name: scheduled-task
spec:
schedule: "15 5 * * 1-5"
concurrencyPolicy: Allow
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: task
image: alpine:3.19
command: ["/bin/sh", "-c", "echo 'task running'"] Last verified:
AWS EventBridge Equivalent
Standard cron expressions often need conversion for AWS EventBridge schedules.
cron(15 5 ? * 1-5 *) Frequently Asked Questions
What specific times does the `15 5 * * 1-5` cron expression trigger?
This cron expression is set to run at 5:15 AM and again at 5:15 PM. These times are observed on Monday, Tuesday, Wednesday, Thursday, and Friday, effectively covering the standard work week.
How does this schedule handle Daylight Saving Time changes?
Cron schedules operate on the server's local time. When Daylight Saving Time begins or ends, the system clock adjusts automatically. This means the cron job will trigger at the new local time, potentially shifting its execution relative to Coordinated Universal Time.
How can I verify that my task ran successfully at 5:15 AM and 5:15 PM on weekdays?
You can confirm successful execution by checking your application logs for entries related to the triggered task around 5:15 AM and 5:15 PM on weekdays. Additionally, monitoring system metrics or setting up alerts for task completion can provide robust verification.
What is a potential pitfall when scheduling tasks twice daily on weekdays?
A key consideration is ensuring that the task is idempotent or can handle being potentially triggered again if a previous run did not complete successfully before the second scheduled time. This is especially important if tasks are resource-intensive or take a significant amount of time.
What is a common variation of this weekday, twice-daily schedule?
A common variation is to adjust the frequency to run every hour during business hours, or to consolidate critical tasks into a single daily run at either the beginning or end of the business day, depending on the specific operational needs.
More schedules like this
Explore Business Hours Schedules →* Try any expression
Standard, Quartz, AWS EventBridge, Jenkins, named schedules (@daily, @hourly…)
* Keep Exploring