About Cron Expression Generator
A cron expression is five space-separated fields — minute, hour, day-of-month, month, day-of-week — that define a recurring schedule: 0 9 * * 1 means every Monday at 09:00. Cron syntax is compact, universal (crontab, Kubernetes CronJob, GitHub Actions, Spring, Quartz, AWS EventBridge)… and notoriously easy to get subtly wrong, because the failure mode is silent: the job just runs at the wrong time, or never.
This generator builds expressions from human choices and explains existing ones, so you can verify a schedule does what you intend before it ships. It runs entirely in your browser.
How to use Cron Expression Generator
- Enter 5 values (one per line or space-separated): minute, hour, day-of-month, month, day-of-week. Use * for any.
- Click Convert to build the cron expression.
- Copy the cron string.
Example
Input
Your input or data here
Output
Result will appear here after running the tool
The five fields, in order
minute (0–59), hour (0–23), day-of-month (1–31), month (1–12), day-of-week (0–7, where both 0 and 7 mean Sunday). Each field accepts: * (any), lists (1,15), ranges (9-17), and steps (*/5 = every 5). Remembering the order is half the battle — the other half is the special semantics below.
* * * * * │ │ │ │ └─ day of week (0-7, 0/7 = Sunday) │ │ │ └────── month (1-12) │ │ └─────────── day of month (1-31) │ └──────────────── hour (0-23) └───────────────────── minute (0-59)
The OR rule — cron's biggest trap
When both day-of-month and day-of-week are restricted (neither is *), POSIX cron runs the job if either matches — not both. 0 9 13 * 5 fires every Friday and every 13th at 09:00, not only on Friday the 13th. This surprises nearly everyone and has caused real over-execution incidents (duplicate billing runs, repeated report emails).
If you need AND semantics (only Friday the 13th), keep one field as * and check the other condition inside the job — e.g. schedule 0 9 13 * * and have the script exit unless date +%u is 5. Quartz (Java) handles this differently with its ? character, which is why Quartz expressions have 6–7 fields and don't paste cleanly into crontab.
Timezones, DST, and the missing 02:30
Classic cron evaluates expressions in the system's local timezone. A 30 2 * * * job does not run on the spring-forward night in DST zones (02:30 never occurs) and runs twice on fall-back night in some implementations. Schedule critical jobs between 03:00 and 04:00 local, or run the scheduler in UTC (Kubernetes CronJob defaults to the kubelet/controller timezone; set .spec.timeZone explicitly since 1.27).
Also know your platform's dialect: standard cron has no seconds field, @daily/@reboot shortcuts are Vixie-cron extensions, AWS EventBridge uses a 6-field variant with ? and years, and GitHub Actions runs in UTC with minimum 5-minute granularity (and delays under load).
Expressions people actually search for
- */5 * * * * — every 5 minutes
- 0 * * * * — hourly, on the hour
- 0 0 * * * — daily at midnight
- 0 9 * * 1-5 — weekdays at 09:00
- 0 0 * * 0 — weekly, Sunday midnight
- 0 0 1 * * — monthly, 1st at midnight
- 0 */6 * * * — every 6 hours (00,06,12,18)
- 30 23 * * 5 — Fridays at 23:30
- 0 0 L * * — last day of month (Quartz/some crons only; POSIX needs a workaround)
Common errors and how to fix them
Job fires far more often than intended
Cause: The OR rule: both day-of-month and day-of-week set, matching on either — or a bare * in minute (* 9 * * * runs 60 times between 09:00 and 09:59).
Fix: Keep one of DOM/DOW as *; always pin the minute field (0 9 * * *, not * 9 * * *).
Job never runs
Cause: Impossible dates (0 0 31 2 * — Feb 31), wrong field order (day/month swapped), or the cron daemon reading a different timezone than you assumed.
Fix: Validate the expression's next runs before deploying; log date at job start once to confirm the effective timezone.
Runs at the wrong hour, consistently
Cause: Server timezone differs from yours (UTC server, local mental model) — the offset equals the error.
Fix: Decide the schedule in the scheduler's timezone. In Kubernetes, set spec.timeZone; in crontab, check /etc/timezone or use CRON_TZ.
Missed or doubled run once a year
Cause: DST transition: the scheduled local time didn't exist (spring) or occurred twice (fall).
Fix: Schedule critical jobs outside 01:00–03:00 local, or run the scheduler in UTC.
Works in crontab, rejected by the app scheduler (or vice versa)
Cause: Dialect mismatch: Quartz's 6–7 fields with seconds and ?, EventBridge's year field, or @daily shortcuts unsupported by strict POSIX parsers.
Fix: Translate between dialects field by field; never paste Quartz expressions into crontab unmodified.
Tips and best practices
- Read expressions right-to-left ('on Monday, at hour 9, minute 0') — it matches how humans state schedules.
- 0 and 7 both mean Sunday in day-of-week; prefer 0 for portability (some old crons reject 7).
- Steps apply to the field's whole range unless bounded: */10 in minutes is 0,10,20,30,40,50; 20-59/10 is 20,30,40,50.
- Names (MON, JAN) are supported by most modern crons and are self-documenting — 0 9 * * MON-FRI reads better than 1-5.
- In crontab, % is special (newline) and must be escaped \% — a surprising cause of 'command truncated' failures.
- Jobs that must not overlap need locking (flock in crontab, concurrencyPolicy: Forbid in Kubernetes) — cron itself happily starts a second instance.
Frequently asked questions
- What do the five fields mean?
- In order: minute (0-59), hour (0-23), day of month (1-31), month (1-12), day of week (0-7; both 0 and 7 are Sunday). Each accepts * (any), lists, ranges, and step values (*/n).
- Why does my day-of-week + day-of-month schedule fire too often?
- POSIX cron ORs the two day fields when both are restricted: 0 9 13 * 5 means 'every 13th OR every Friday'. For AND semantics, keep one field * and enforce the other condition inside the job itself.
- What timezone do cron expressions use?
- The scheduler's local timezone — the system clock for crontab, configurable in Kubernetes (spec.timeZone) and most cloud schedulers. There is no timezone inside the expression itself, so document it alongside the schedule.
- How do I run something every 90 minutes?
- You can't express 'every 90 minutes' in one standard cron line (steps don't carry across hour boundaries). Use two lines (0 0,3,6,9,12,15,18,21 * * * and 30 1,4,7,10,13,16,19,22 * * *), or a scheduler with interval semantics (systemd timers, EventBridge rate()).
- Does standard cron support seconds?
- No — five fields, minute resolution. Seconds appear in Quartz (6-7 fields) and some frameworks. If a tool demands six fields, it's a dialect, and expressions aren't directly portable to crontab.
- What happens if my server reboots at the scheduled time?
- Standard cron just misses the run — there is no catch-up. anacron, systemd timers with Persistent=true, or Kubernetes CronJob's startingDeadlineSeconds provide missed-run semantics when you need them.
Embed this tool
Add Cron Expression Generator to your own site, blog post, or internal docs — free, no signup. The widget runs entirely in your visitors' browsers, same as it does here.