Cron expressions are one of those things that look intimidating the first time you encounter them — five or six cryptic fields of asterisks, numbers, and slashes — and then become obvious the moment someone explains the pattern. The free Cron Expression Generator lets you build any cron schedule visually and shows the next 10 run times instantly so you can confirm it does what you expect before it goes anywhere near a production server. This guide explains everything: the syntax field by field, every special character with practical examples, 30+ ready-to-use expressions, timezone gotchas, and the differences between Linux crontab, Kubernetes CronJobs, AWS EventBridge, and GitHub Actions schedules.
The 5-Field Cron Syntax — Explained Once and for All
A standard cron expression has five fields, separated by spaces:
┌───────── minute (0 - 59) │ ┌─────── hour (0 - 23) │ │ ┌───── day of month (1 - 31) │ │ │ ┌─── month (1 - 12 or JAN-DEC) │ │ │ │ ┌─ day of week (0 - 7 or SUN-SAT, 0 and 7 are both Sunday) │ │ │ │ │ * * * * *
The cron daemon (or scheduler) checks the current time against every field. The job runs only when all five fields match simultaneously. An asterisk in any field means "match everything" — any value for that field is accepted. This is why * * * * * runs every minute: every possible value matches every field.
Field 1: Minute (0–59)
Controls which minute(s) within an hour the job runs.
| Value | Meaning |
|---|---|
| 0 | At the top of the hour (minute zero) |
| 30 | At the half-hour mark |
| */15 | Every 15 minutes (at 0, 15, 30, 45) |
| 0,30 | At minute 0 and minute 30 (twice per hour) |
| 10-20 | Every minute from the 10th to the 20th |
Field 2: Hour (0–23)
Controls which hour(s) the job runs. Uses 24-hour clock — 0 is midnight, 12 is noon, 23 is 11 PM.
| Value | Meaning |
|---|---|
| 0 | Midnight (00:00) |
| 9 | 9 AM |
| 17 | 5 PM (17:00) |
| 9,17 | 9 AM and 5 PM (twice a day) |
| 9-17 | Every hour from 9 AM to 5 PM |
| */6 | Every 6 hours (at 0, 6, 12, 18) |
Field 3: Day of Month (1–31)
Controls which day(s) of the month the job runs. Values are 1–31. Setting this to a non-star value while day-of-week is also non-star triggers an OR — the job runs on days matching either field.
Field 4: Month (1–12 or JAN–DEC)
Controls which months the job runs. Accepts numeric values (1=January through 12=December) or three-letter abbreviations (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC). A value of */3 means every quarter (January, April, July, October).
Field 5: Day of Week (0–7 or SUN–SAT)
Controls which weekdays the job runs. Both 0 and 7 represent Sunday — this is a historical quirk. 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday. Accepts three-letter names (MON, TUE, WED, THU, FRI, SAT, SUN). A range of 1-5 means Monday through Friday.
Every Special Character — With Real Examples
Asterisk (*) — Any Value
* * * * * # every minute 0 * * * * # every hour, on the hour 0 0 * * * # every day at midnight
Comma (,) — List of Values
0 9,17 * * * # at 9 AM and 5 PM every day 0 0 1,15 * * # at midnight on the 1st and 15th of each month 0 9 * * 1,3,5 # at 9 AM on Monday, Wednesday, Friday
Hyphen (-) — Range
0 9-17 * * * # every hour from 9 AM to 5 PM 0 9 * * 1-5 # at 9 AM on every weekday (Mon-Fri) 0 0 1-7 * 1 # at midnight on the first Monday of every month (approx)
Slash (/) — Step / Interval
*/5 * * * * # every 5 minutes */15 * * * * # every 15 minutes 0 */2 * * * # every 2 hours, on the hour 0 */6 * * * # every 6 hours (00:00, 06:00, 12:00, 18:00)
The slash means "start at X, then every N". So */5 in the minute field means "start at 0, then every 5" — giving 0, 5, 10, 15… You can also combine with ranges: 10-50/10 means "from minute 10 to minute 50, every 10 minutes" — giving 10, 20, 30, 40, 50.
Hash (#) — Nth Weekday of Month (Quartz/Advanced)
0 9 * * 5#1 # 9 AM on the FIRST Friday of each month 0 9 * * 2#3 # 9 AM on the THIRD Tuesday of each month
The # character is supported in Quartz Scheduler (Java) and some enterprise cron implementations, but not in standard Linux crontab. Check your target environment before using it.
L — Last (Quartz/Advanced)
0 23 L * * # 11 PM on the last day of every month 0 9 * * 5L # 9 AM on the last Friday of every month
W — Nearest Weekday (Quartz/Advanced)
0 9 15W * * # 9 AM on the weekday nearest to the 15th of the month
If the 15th is a Saturday, it runs on the 14th (Friday). If the 15th is a Sunday, it runs on the 16th (Monday). Useful for month-end payroll runs or billing cycles that must land on a business day.
30+ Ready-to-Use Cron Expressions
| Expression | Schedule |
|---|---|
| * * * * * | Every minute |
| */5 * * * * | Every 5 minutes |
| */10 * * * * | Every 10 minutes |
| */15 * * * * | Every 15 minutes |
| 0 * * * * | Every hour on the hour |
| 0 */2 * * * | Every 2 hours |
| 0 */6 * * * | Every 6 hours (4x per day) |
| 0 0 * * * | Every day at midnight |
| 0 6 * * * | Every day at 6 AM |
| 0 9 * * * | Every day at 9 AM |
| 0 12 * * * | Every day at noon |
| 0 18 * * * | Every day at 6 PM |
| 0 23 * * * | Every day at 11 PM |
| 0 9,17 * * * | Every day at 9 AM and 5 PM |
| 0 9 * * 1-5 | 9 AM every weekday (Mon–Fri) |
| 0 9 * * 1 | 9 AM every Monday |
| 0 9 * * 5 | 9 AM every Friday |
| 0 0 * * 0 | Midnight every Sunday |
| 0 0 1 * * | Midnight on the 1st of every month |
| 0 0 15 * * | Midnight on the 15th of every month |
| 0 0 1,15 * * | Midnight on 1st and 15th of each month |
| 0 0 L * * | Midnight on last day of each month |
| 0 0 1 */3 * | Midnight on 1st of every quarter (Jan, Apr, Jul, Oct) |
| 0 0 1 1 * | Midnight on January 1st (New Year) |
| 0 0 * * 1 | Midnight every Monday (weekly reset) |
| 30 8 * * 1-5 | 8:30 AM every weekday (standup time) |
| 0 2 * * * | 2 AM daily (nightly backup window) |
| 0 3 * * 0 | 3 AM every Sunday (weekly maintenance) |
| 0 9-17 * * 1-5 | Every hour 9 AM–5 PM on weekdays |
| */30 9-17 * * 1-5 | Every 30 min during business hours |
Platform Differences — Linux, Kubernetes, AWS, GitHub Actions
Cron syntax is not perfectly standardised. Different platforms support different features and have different edge cases. This is the source of most "my cron expression works on Linux but fails on AWS" confusion.
Linux crontab (Standard)
The original. Five fields. Supports *, ,, -, / in all fields. Supports @daily, @weekly, @monthly, @yearly, @reboot shortcuts. Does NOT support L, W, or #. Runs in the system timezone — check timedatectl to see what timezone your server is in.
Kubernetes CronJob
Uses standard 5-field cron syntax. Defaults to UTC timezone. From Kubernetes 1.25+, you can specify a timezone with the spec.timeZone field (e.g., timeZone: "Asia/Kolkata"). Important caveat: Kubernetes CronJobs have a startingDeadlineSeconds field — if the cluster is unavailable when a job is supposed to start, it will miss the schedule if the missed window exceeds this deadline.
AWS EventBridge (CloudWatch Events)
Uses a 6-field format with year appended: minute hour day-of-month month day-of-week year. Critical difference: you cannot specify both day-of-month and day-of-week as non-star values. One must always be ?. For example: cron(0 12 * * ? *) for daily at noon UTC, or cron(0 12 ? * MON-FRI *) for weekdays at noon. Always UTC — no timezone configuration available for cron expressions (use rate expressions if you need relative timing).
GitHub Actions
Uses standard 5-field cron syntax under the schedule trigger. Always runs in UTC. Minimum interval is every 5 minutes — GitHub will not queue a workflow more frequently. Note: scheduled workflows on the default branch do not run on forks, and GitHub may delay or skip scheduled runs on repositories with low activity. Always UTC — plan accordingly for IST workflows (UTC + 5:30).
| Platform | Fields | Timezone | L/W/# Support |
|---|---|---|---|
| Linux crontab | 5 | System TZ | No |
| Kubernetes CronJob | 5 | UTC (configurable 1.25+) | No |
| AWS EventBridge | 6 (+ year) | UTC only | Partial (L, W) |
| GitHub Actions | 5 | UTC only | No |
| Quartz Scheduler (Java) | 6 (+ seconds) | Configurable | Yes (L, W, #) |
The Timezone Trap — Why Your Cron Runs at the Wrong Time
This is the most common cron mistake in teams working across time zones. The cron expression itself has no timezone information — it is always interpreted in the timezone of the system or platform running it. On most cloud servers and CI platforms, that timezone is UTC.
India Standard Time (IST) is UTC+5:30. If you want a cron job to run at 9:00 AM IST, you need to subtract 5 hours 30 minutes to get the UTC equivalent: 3:30 AM UTC. The cron expression on a UTC server is: 30 3 * * *
Common IST-to-UTC conversions:
| IST Time | UTC Equivalent | Cron Expression (UTC) |
|---|---|---|
| 6:00 AM IST | 12:30 AM UTC | 30 0 * * * |
| 9:00 AM IST | 3:30 AM UTC | 30 3 * * * |
| 12:00 PM IST | 6:30 AM UTC | 30 6 * * * |
| 6:00 PM IST | 12:30 PM UTC | 30 12 * * * |
| 11:30 PM IST | 6:00 PM UTC | 0 18 * * * |
| Midnight IST | 6:30 PM UTC (prev day) | 30 18 * * * |
Note that IST midnight (00:00 IST) falls on the previous day in UTC (18:30 UTC), which can cause day-of-week calculations to shift. A cron job meant to run at midnight Sunday IST actually fires on Saturday UTC — if your day-of-week field is set to Sunday, it will miss.
Common Cron Mistakes and How to Fix Them
-
Assuming the server timezone is local time: Cloud servers default to UTC. Always check
dateon the server to confirm timezone before deploying a time-sensitive cron job. -
Using both day-of-month and day-of-week as non-star: In Linux cron, this triggers an OR — the job runs on either condition. If you want "first Monday of the month," you cannot express that precisely with standard cron syntax. Use the
#character (Quartz only) or add a conditional check inside the script itself. -
Step values that do not align to hour boundaries:
*/7in the minute field gives you minutes 0, 7, 14, 21, 28, 35, 42, 49, 56 — then the sequence resets at the top of the next hour back to 0. This means the gap between 56 and the next 0 is 4 minutes, not 7. If you need exactly every N minutes without drift, use a proper interval scheduler rather than cron. -
Forgetting 0-indexed day-of-week: Sunday is 0 (or 7). Setting day-of-week to 7 for Sunday works in most implementations but not all. Use 0 for safety, or use the name
SUN. - Relying on cron for sub-minute tasks: Cron minimum resolution is 1 minute. Use systemd timers, Celery beat, or application-level scheduling for sub-minute intervals.
- Not checking for missed executions: If the server is down when a cron job was scheduled to run, standard cron misses it entirely — there is no catch-up mechanism. For critical jobs, add monitoring (Cronitor, Healthchecks.io) that alerts you when an expected execution does not happen.
How to Use the Cron Expression Generator
- Choose your schedule type: Select from presets (every N minutes, daily, weekly, monthly) or go to the manual field editor for full control.
- Fill in each field: The generator validates each field in real time and highlights errors — invalid ranges, out-of-bounds values, and syntax errors are flagged before you copy the expression.
- Check the next run times: The tool immediately shows the next 10 scheduled executions in plain English (e.g., "Monday, March 17 2026 at 9:00 AM"). This is the fastest way to confirm your expression is correct without having to mentally parse it.
-
Select your platform: Choose Linux cron, Kubernetes, GitHub Actions, or AWS EventBridge to get the correct format for your target — including the 6-field format for AWS and the
?wildcard requirements. - Copy the expression: One click copies the validated cron string, ready to paste into your crontab, CI config, or cloud scheduler.
Final Thoughts
Cron expressions look cryptic because they are designed for density — five fields that fit in a terminal line and express an enormous range of schedules. Once you understand that each field is just a set constraint on a time component, and that the special characters are consistent shorthand for common patterns (every N, list, range), writing and reading cron becomes fast. The expression 30 3 * * 1-5 takes about two seconds to read as "3:30 AM every weekday" once the syntax is internalised.
The part that always trips people up is the timezone mismatch — a cron expression deployed to a UTC server thinking "9 AM" is local time. Use the generator's next-run preview to catch this before it causes a job to fire at 3:30 AM when your on-call team was not expecting it.
Open the free Cron Expression Generator, build your schedule visually, verify the next 10 run times, and copy a validated expression — no guessing, no manual parsing, no production surprises.