Quick Start Guide to Cron Syntax
Everything you need to know to write reliable cron expressions — from first principles to production best practices.
What is a Cron Job?
A cron job is a time-based task scheduler found in Unix-like operating systems and modern cloud platforms. The name comes from the Greek word "chronos" (time), and the daemon — crond — has been running background tasks on servers since the 1970s. Today, cron-style scheduling powers everything from simple backup scripts on a single VPS to complex distributed workflows orchestrated across multi-region cloud infrastructure.
At its core, a cron job consists of two parts: a schedule expression that defines when the task runs, and a command or target that defines what happens. The schedule expression — commonly called a "cron expression" — is a compact string of fields that encodes timing information in a machine-readable format. Learning to read and write these expressions is a foundational skill for any developer working with automation, CI/CD pipelines, or cloud infrastructure.
Modern platforms have extended the original Unix syntax to support more granular scheduling. AWS EventBridge adds a year field and uses question marks. Quartz (used in Java/Spring applications) adds a seconds field and special modifiers like L (last), W (weekday), and # (nth occurrence). Kubernetes CronJobs use standard 5-field Unix cron but add concurrency policies and deadline controls. Understanding these differences is critical for deploying reliable schedules across heterogeneous environments.
Understanding the 5 Fields
A standard Unix cron expression contains exactly five fields, separated by spaces. Each field controls one dimension of timing. Together, they answer the question: "At which minute, of which hour, on which day(s), in which month(s), and on which weekday(s) should this job execute?"
Minute (0–59): Which minute of the hour the job fires. A value of 0 means the top of the hour; */5 means every five minutes.
Hour (0–23): Uses 24-hour time.9 is 9 AM, 17 is 5 PM. Ranges like 9-17 restrict execution to business hours.
Day of Month (1–31): Which calendar day. Be careful with values above 28 — not every month has 31 days. Use L in Quartz for "last day" to avoid edge cases.
Month (1–12 or JAN–DEC): Which month(s) of the year. Supports numbers, three-letter abbreviations, ranges, and step values.
Day of Week (0–7 or SUN–SAT): Both 0 and 7 represent Sunday in Unix cron. Quartz uses 1=Sunday through 7=Saturday. This difference is a common source of bugs when migrating between platforms.
Special characters expand expression power: * (any value), , (list), - (range), / (step). Mastering these four operators lets you express virtually any repeating schedule.
Why Timezones Matter
Cron expressions don't inherently carry timezone information — the system or platform they run on determines the reference clock. This creates a class of subtle bugs that only manifest twice a year: during Daylight Saving Time transitions. A job scheduled for 2:30 AM might execute twice on "fall back" night, or be skipped entirely on "spring forward" night.
Unix crontab uses the system's configured timezone (typically set in /etc/timezone). If your server is in UTC but your business operates in US/Eastern, every schedule needs manual offset calculation.
AWS EventBridge always evaluates cron expressions in UTC. To schedule a job at 9 AM Eastern, you must account for the UTC offset — and remember it changes between EST (-5) and EDT (-4).
Kubernetes CronJobs default to the kube-controller-manager's timezone (usually UTC) but support the timeZone field since v1.27 (stable). Always set this explicitly to avoid surprises after cluster upgrades.
Best practice: Always define schedules in UTC and convert for display, or explicitly configure the timezone on platforms that support it. Never assume the system clock matches your users' expectations. Our generator shows execution times in your local timezone precisely to help you catch these mismatches before they hit production.
Cron Expression Generator
Build, validate, and understand cron expressions with our visual builder. Supports Unix, Quartz, AWS EventBridge, Spring Boot, and Azure Functions dialects.
Visual Builder
Linux/Unix — 5 fieldsEvery minute
⌘+Shift+Dto copy description
Learn More About Cron Expressions
A cron expression is a compact, whitespace-delimited string that defines a recurring schedule. Originally designed for the Unix cron daemon in the 1970s, the format has evolved into multiple dialects used across cloud platforms, container orchestrators, and application frameworks. Understanding the difference between field formats is critical to avoiding silent scheduling failures in production.
Standard 5-Field Format (Unix/Linux crontab)
The classic cron format uses exactly five fields, each separated by a single space. This is the format used bycrontab -e on Linux/macOS, Kubernetes CronJobs, GitHub Actions schedules, and most CI/CD pipelines.
┌───────────── minute (0–59)
│ ┌───────────── hour (0–23)
│ │ ┌───────────── day of month (1–31)
│ │ │ ┌───────────── month (1–12 or JAN–DEC)
│ │ │ │ ┌───────────── day of week (0–6 or SUN–SAT)
│ │ │ │ │
* * * * *6-Field Format (AWS EventBridge, Spring, Azure)
Many modern platforms extend the standard with an additional field. AWS EventBridge adds a year field at the end, while Spring Boot's @Scheduled and Azure Functions Timer Triggers prepend a seconds field. Confusing these formats is the #1 cause of "my cron job runs at the wrong time" bugs.
┌───────────── minute (0–59)
│ ┌───────────── hour (0–23)
│ │ ┌───────────── day of month (1–31)
│ │ │ ┌───────────── month (1–12 or JAN–DEC)
│ │ │ │ ┌───────────── day of week (SUN–SAT or 1–7)
│ │ │ │ │ ┌───────────── year (1970–2199)
│ │ │ │ │ │
* * * * ? *┌───────────── second (0–59)
│ ┌───────────── minute (0–59)
│ │ ┌───────────── hour (0–23)
│ │ │ ┌───────────── day of month (1–31)
│ │ │ │ ┌───────────── month (1–12 or JAN–DEC)
│ │ │ │ │ ┌───────────── day of week (0–6 or SUN–SAT)
│ │ │ │ │ │
0 * * * * *7-Field Format (Quartz Scheduler)
Java's Quartz Scheduler uses the most extended format with 7 fields: seconds, minutes, hours, day-of-month, month, day-of-week, and an optional year. Quartz also introduces the ? character which means "no specific value" — required in either day-of-month or day-of-week (you must use ? in one of them).
Key Differences at a Glance
| Feature | Unix | AWS | Quartz | Spring/Azure |
|---|---|---|---|---|
| Fields | 5 | 6 | 6–7 | 6 |
| Seconds | No | No | Yes | Yes |
| Year | No | Yes | Optional | No |
| ? character | No | Yes | Required | Yes |
| L/W/# chars | No | L, W | L, W, # | No |
| DOW numbering | 0=Sun | 1=Sun | 1=Sun | 0=Sun |
AWS EventBridge / CloudWatch Events
AWS EventBridge uses a 6-field cron format with a mandatory year field. All times are evaluated in UTC only — there is no timezone parameter. You must use ? in either day-of-month or day-of-week (not both can be *).
cron(0 9 ? * MON-FRI *)
# In AWS CLI:
aws events put-rule \
--name "weekday-morning" \
--schedule-expression "cron(0 9 ? * MON-FRI *)" \
--state ENABLEDKey differences from Unix cron: Days of week are 1-7 (SUN=1) instead of 0-6. The year field supports 1970–2199. AWS supports L (last) and W (nearest weekday) in the day-of-month field.
Kubernetes CronJobs
Kubernetes CronJobs use the standard 5-field Unix cron format. The schedule is evaluated against the timezone of the kube-controller-manager. Since Kubernetes v1.25+, you can set .spec.timeZone explicitly.
apiVersion: batch/v1
kind: CronJob
metadata:
name: daily-backup
spec:
schedule: "30 2 * * *"
timeZone: "America/New_York" # K8s 1.25+
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
containers:
- name: backup
image: myregistry/backup:latest
command: ["/bin/sh", "-c", "./backup.sh"]
restartPolicy: OnFailureBest practices: Always setconcurrencyPolicy to prevent overlapping jobs. Use startingDeadlineSeconds to handle missed schedules gracefully. Monitor with kubectl get cronjobs.
kubectl create cronjob test --image=busybox --schedule="*/5 * * * *" --dry-run=client -o yaml to generate a manifest quickly.Azure Functions Timer Trigger
Azure Functions uses a 6-field NCRONTAB format with seconds as the first field. By default, timers run in UTC. Set the WEBSITE_TIME_ZONE app setting to use a specific timezone (Windows timezone IDs on Windows hosts, IANA on Linux).
// function.json
{
"bindings": [
{
"name": "myTimer",
"type": "timerTrigger",
"direction": "in",
"schedule": "*/30 * * * * *"
}
]
}
// C# attribute syntax:
[Function("TimerFunction")]
public void Run(
[TimerTrigger("0 */5 * * * *")] TimerInfo timer)
{
// Runs every 5 minutes at second 0
}Azure-specific features: Supports%schedule% syntax to reference app settings. The RunOnStartup property triggers execution when the function app starts. Use UseMonitor to prevent missed schedule catch-ups.
1Confusing field order between platforms
0 0 9 * * 1-5 (intended: "weekdays at 9 AM" in Unix format)0 9 * * 1-5 (Unix: 5 fields only — no seconds field)A common mistake is prepending "0" for seconds in a 5-field Unix cron, accidentally shifting all fields. The "0" becomes the minute, "9" becomes the hour incorrectly, etc.
2Using * in both day-of-month and day-of-week (AWS/Quartz)
cron(0 9 * * * *) — AWS EventBridge rejects thiscron(0 9 ? * * *) or cron(0 9 * * ? *)In AWS and Quartz, you must use "?" in either DOW or DOM. Using "*" in both is ambiguous and will fail validation.
3Day-of-week numbering differences
0 9 * * 7 (expecting Sunday in AWS — but 7 is SAT in some systems)0 9 * * SUN (use names for clarity across platforms)Unix uses 0=Sunday (with 7 as an alias for Sunday in some implementations). AWS uses 1=Sunday through 7=Saturday. Always use SUN-SAT names to avoid confusion.
4Forgetting UTC-only evaluation in AWS
Scheduling "9 AM local" without timezone conversionConvert to UTC first: 9 AM EST = cron(0 14 ? * * *) in winterAWS EventBridge evaluates all cron expressions in UTC. You must manually convert your local time to UTC, and account for DST changes twice a year.
5Using step values with wrong base
*/3 9-17 * * * (expecting every 3 min only during business hours)0/3 9-17 * * * (same result, but explicit start at 0)While */3 works the same as 0/3 for minutes (both start at 0), using explicit start values like 5/15 (starting at minute 5) gives you more control. The gotcha is that */3 in hour field means 0,3,6,9,12,15,18,21 — not "every 3 hours starting from the current hour".
6Overlapping time windows in Kubernetes CronJobs
Running a 10-minute job with "*/5 * * * *" scheduleSet concurrencyPolicy: Forbid and startingDeadlineSecondsIf your job takes longer than the interval between executions, Kubernetes will start overlapping instances. Use concurrencyPolicy: Forbid to skip new runs while one is active, or Replace to kill and restart.
7Month and weekday ranges with step values
0 0 * 1-12/3 * (expecting quarterly — Jan, Apr, Jul, Oct)0 0 1 1,4,7,10 * (explicit quarterly months)While 1-12/3 does mean months 1,4,7,10, it is easier to misread. More importantly, this pattern fails for edge cases: 1-6/4 gives only months 1 and 5 (not 4 values). Be explicit with lists for clarity.
8Azure Timer Trigger cold starts
Expecting sub-second precision from "*/1 * * * * *" on Consumption planUse Premium plan for time-sensitive jobs or add UseMonitor=trueAzure Functions on the Consumption plan can have cold starts of 1-10+ seconds. Timer triggers may fire late after the app wakes from idle. Use Premium/Dedicated plans or the RunOnStartup property for critical schedules.
Under the Hood
How our engine unifies five distinct scheduling syntaxes into one accurate, real-time interface.
Multi-Dialect Regex Parser
Each platform has unique syntax rules. Our parser uses dialect-specific regex patterns to validate and tokenize expressions:
Cross-Platform Field Normalization
Platforms disagree on fundamentals. Our normalization layer handles the conflicts transparently:
- →Day-of-week numbering: Unix uses 0-6 (Sun=0), Quartz uses 1-7 (Sun=1), AWS uses 1-7 (Sun=1)
- →Mutual exclusion: Quartz requires
?in either DOM or DOW — never both with values - →Year field: AWS and Quartz support it; Unix and Azure do not
- →Seconds precision: Quartz and Azure include seconds; Unix and AWS do not
Platform-Aware Validation
Validation isn't one-size-fits-all. Each dialect has specific rules that our engine enforces:
Timezone-Aware Run Calculation
Computing "next runs" correctly requires handling edge cases most tools ignore:
- •DST transitions: A 2:30 AM job during spring-forward doesn't fire — we detect and warn about this
- •Month boundaries: "31st of every month" correctly skips months with fewer days
- •Leap years: Feb 29 schedules are validated against the actual calendar
- •Efficient iteration: Uses field-jumping instead of brute-force minute scanning for fast previews
Processing Pipeline
All processing happens client-side in your browser — zero server round-trips, instant feedback.