Cron Expression Builder & Tester
Describe any cron expression in plain English and preview the next 10 fires in your timezone.
- [FREE]
- [NO_SIGNUP]
- [NO_UPLOAD]
How to use the cron expression builder
- Start from a preset. The dropdown has 12 common patterns — every minute, every 5 minutes, hourly, daily at 3 AM, weekdays at 9 AM, monthly, yearly. Pick the closest one and tweak from there.
- Edit the expression. The field breakdown below the input shows each of the five fields with its current value. Invalid expressions border in red.
- Read the meaning. The “Means” line restates your expression in plain English. If it doesn’t say what you expected, your expression is wrong.
- Set the timezone. Defaults to your browser’s local zone, but cron runners like Cloudflare Cron Triggers and GitHub Actions use UTC. Pick the zone the runner will use, not the one you live in, to see when the job will actually fire.
- Verify with the next-fires table. 10 upcoming times in your selected zone, with the UTC equivalent and the delta from the previous fire so you can spot oddities like DST transitions.
Anatomy of a cron expression
┌──────────── 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 = Sunday)
│ │ │ │ │
* * * * *
Operators
| Operator | Meaning | Example |
|---|---|---|
* | Any value | * * * * * — every minute |
, | List | 0 9,17 * * * — 9 AM and 5 PM |
- | Range | 0 9 * * 1-5 — weekdays at 9 AM |
/ | Step | */15 * * * * — every 15 minutes |
Combine them: 0 9-17/2 * * 1-5 fires at 9, 11, 13, 15, 17 (every two hours from 9 to 17) on weekdays.
Common patterns
| Goal | Expression |
|---|---|
| Every minute | * * * * * |
| Every 5 minutes | */5 * * * * |
| Every 15 minutes | */15 * * * * |
| Every hour at :00 | 0 * * * * |
| Every 6 hours | 0 */6 * * * |
| Daily at midnight | 0 0 * * * |
| Daily at 3 AM | 0 3 * * * |
| Weekdays at 9 AM | 0 9 * * 1-5 |
| First of every month at 00:00 | 0 0 1 * * |
| Quarterly | 0 0 1 */3 * |
| Annually | 0 0 1 1 * |
Gotchas
Day-of-month and day-of-week interact
0 0 1 * 1 means the 1st of the month OR every Monday, not the 1st that is also a Monday. POSIX cron uses OR semantics when both fields are restricted. Most modern runners follow this. If you really need AND, do the filter in your job.
Day-of-week numbering varies
- POSIX / Unix cron / this tool / cron-parser: 0 = Sunday, 6 = Saturday.
- Quartz / Spring: 1 = Sunday, 7 = Saturday.
- AWS EventBridge / Azure Functions (Quartz-style): 1 = Sunday.
Always check what your runner expects before copying an expression between systems.
Skipped days
0 0 31 * * only fires on the 31st of months that have one. Use your runner’s “last day of month” syntax (L in Quartz/AWS) or schedule on the 1st instead.
Daylight Saving Time
A job at 0 2 * * * in a DST-aware timezone fires once at 02:00 every day — except on the spring-forward day, when 02:00 may not exist (it jumps from 01:59 to 03:00) and the job may be skipped, or on the fall-back day, when 02:00 happens twice and the job may fire twice. Many runners handle these explicitly; check your docs. If timing is critical, schedule in UTC.
Where cron expressions are used
- Unix
crontab— the classic. - Kubernetes CronJob —
spec.scheduleis a cron expression, evaluated in UTC by default. - GitHub Actions —
on.schedule.cron, also UTC. - Cloudflare Workers Cron Triggers — UTC.
- AWS EventBridge Scheduler — supports a Quartz-style 6-field cron with year and
?for day-of-month/day-of-week. - Spring
@Scheduled— 6-field cron with seconds. - node-cron, agenda, BullMQ — usually POSIX 5-field with optional seconds.
Privacy and security
The tool is a single HTML page with a small JavaScript bundle. Your expressions never leave your device. The share link encodes state in the URL fragment (#…) — that part of a URL is not sent to servers. Verify in DevTools → Network: no outbound requests after the page loads.
Related tools
- JSON ↔ YAML Converter — convert a Kubernetes CronJob manifest from one format to the other.
- JSON Formatter & Error Reviewer — pretty-print a job definition with its schedule.
- Diff Checker — compare two cron schedules side-by-side.
Frequently asked questions
Is my cron expression sent to a server?
No. Parsing and the next-fire preview both run in your browser tab. Open DevTools → Network and you will see no outbound request with your input. The share link encodes state into the URL hash (#…), which the browser does not transmit to servers.
Which cron flavor does this use?
Standard 5-field POSIX cron: minute, hour, day-of-month, month, day-of-week. The parser also accepts JAN–DEC and SUN–SAT names. Six-field (with seconds) and seven-field (with year) extensions used by Quartz and AWS EventBridge are not portable and not the default here — pick a runner that documents its exact dialect before using them.
What timezone does the preview use?
Whatever you pick in the Timezone dropdown. On first load the tool detects your local timezone via the browser. Pick UTC to see what most cron-on-a-server jobs use, or any IANA zone (America/New_York, Europe/Paris, etc.) to match the runner you target. Cloudflare Cron Triggers, GitHub Actions, and Kubernetes CronJobs all run in UTC by default.
Why does my Friday 13:00 schedule fire at a different UTC time in summer vs winter?
Daylight Saving Time. The cron expression is evaluated in the chosen timezone, but the preview shows the UTC equivalent which shifts by one hour between DST and standard time. The local time stays constant.
What does "day-of-month 31" do in months with fewer days?
It is skipped. `0 0 31 * *` only fires on the 31st of January, March, May, July, August, October, and December. Use a different rule (`0 0 L * *` if your runner supports L, or `0 0 1 * *` for the 1st of each month) if you really want monthly behavior.
Why are some preset expressions different from what my runner shows?
Some runners (Quartz, Spring) use day-of-week 1–7 with 1 = Sunday. Standard POSIX cron uses 0–6 with 0 = Sunday. This tool follows POSIX. If your runner is different, check its docs and adjust.
Does this handle special strings like @hourly or @daily?
No. Translate them yourself: @hourly = 0 * * * *, @daily = 0 0 * * *, @weekly = 0 0 * * 0, @monthly = 0 0 1 * *, @yearly = 0 0 1 1 *. The presets list has all of these spelled out.
Can I see when a schedule last fired?
The preview shows the next fires, not the previous ones. If you need backfill behavior, your runner is the source of truth — most ship a "history" or "last run" view in their UI.
How accurate is the local-time formatting?
It uses Intl.DateTimeFormat with your selected timezone. DST transitions are honored. The values you see are exactly what a properly-configured runner would emit at those moments.
Is the cron tool really free?
Yes. No signup, no account, no ads, no telemetry on your input. The source is on the project repository.