Cron is the oldest automation tool still in daily use — and the one most people configure by copy-paste. The syntax is small enough to learn in ten minutes and weird enough to cause a 3 AM incident when you get it wrong.
The Cron Parser computes the next run times for any expression, which makes every rule in this article testable in seconds instead of learnable through outages.
The five fields
* * * * *
│ │ │ │ │
│ │ │ │ └── day of week (0–7, 0 and 7 = Sunday)
│ │ │ └──── month (1–12, or jan–dec)
│ │ └────── day of month (1–31)
│ └──────── hour (0–23)
└────────── minute (0–59)
The order is the thing everyone gets wrong at least once: minute comes first. 30 2 * * * is 02:30, not 30:02.
The building blocks
| Syntax | Meaning | Example |
|---|---|---|
* |
Every value | * * * * * — every minute |
5 |
Exact value | 0 9 * * * — 09:00 daily |
a-b |
Range | 9-17 — 9 through 17 |
*/n |
Step | */15 * * * * — every 15 minutes |
a-b/n |
Range with step | 9-17/2 — 9, 11, 13, 15, 17 |
a,b,c |
List | 0,30 * * * * — at :00 and :30 |
jan–dec, sun–sat |
Names | 0 9 * jan mon * — January Mondays (some implementations) |
Rule 1: the classic gotcha — two day fields
Both day of month and day of week have * defaults, and when both are restricted, either matching counts. So:
0 0 1 * 1
runs every Monday AND on the 1st of every month — not "the first Monday". This is the single most common cron surprise. If you want "the first Monday", you need the # extension (0 0 * * 1#1 in extended syntaxes) or a wrapper script that checks the date.
Rule 2: timezone is the server's, always
Cron has no timezone field in the classic 5-field form. A server running UTC runs your "8 AM" job at 8 AM UTC — which is 10 AM in Cairo in summer and 11 AM in winter. Fix: run servers in UTC and schedule in UTC, or use CRON_TZ where supported.
Rule 3: DST is a lie detector
When clocks jump forward, an hour simply doesn't exist; when they jump back, it happens twice. Most cron implementations handle this by running at the (possibly shifted) wall-clock time — but "once daily at 02:30" can become zero or two runs. For anything that must be exactly-once, prefer UTC (no DST).
Rule 4: no backfill
If the server was down at 02:30, the 02:30 job doesn't run at 03:00. Cron is fire-and-forget. Mission-critical jobs need catch-up logic or an external scheduler.
Rule 5: minute granularity is the floor
Cron's smallest unit is one minute. Sub-minute scheduling (every 30 seconds) is not cron's job — that's a systemd timer with OnUnitActiveSec=30s or a proper queue.
Test before you trust
The parser is one POST away:
curl -X POST https://yas.sh/api/v1/tools/cron-parser -d '{"input":"*/15 * * * *","count":5}'
{ "expression": "*/15 * * * *", "valid": true,
"next": ["2026-08-08T12:15:00.000Z", "2026-08-08T12:30:00.000Z", "..."] }
Run your expression, read the next five times, and ask: is this what I meant? If it is, schedule it. If not, the parser just saved you a 3 AM pager call — which is exactly what a ten-minute investment in cron syntax is worth.
The five fields and their traps
A cron expression is five whitespace-separated fields: minute (0–59), hour (0–23), day of month (1–31), month (1–12), and day of week (0–7, where both 0 and 7 are Sunday). Getting the fields right is only half the battle; the traps are where most mistakes live:
- Day of month and day of week are OR-ed in most implementations.
0 0 1 * 1runs on the first of the month and on every Monday — not "the first Monday." This is the single most surprising cron behavior. - Minute zero is the default and the one most people forget.
* * * * *runs every minute; leaving the minute field as*when you want hourly produces a much noisier schedule than intended. - Weekday indexing. Both 0 and 7 are Sunday, and many people write
7expecting Saturday. When in doubt, pin it down explicitly. - Non-standard extensions. Some schedulers add
*/5step syntax,H(hash, in Jenkins), or seconds as a sixth field. An expression that parses in one scheduler may not in another, so know your target.
A parser that shows you the next occurrences is the fastest way to catch these traps — an expression that produces "next Monday at 3am" tells you instantly whether you meant what you wrote.
Testing and deploying cron safely
Before a cron job touches production data, verify it the way you would any other change: run the parser, read the next several occurrences, and confirm the timing matches your intent. Then test the job itself on a small, safe scale before letting it run unattended. Schedule a dry-run or a first execution in a controlled way, and make the job idempotent so a re-run does not duplicate work (the webhooks automation guide covers the idempotency and logging discipline that applies here too). Finally, make sure your cron host is the one you think it is — the timezone of the server, not your local time, is what the schedule follows.
Using cron in link automation
Cron is the natural scheduler for link automation. The recurring tasks — refreshing campaign links, running expiry audits, sending summary reports, checking click thresholds — all map cleanly to a five-field schedule, and they pair with the API. For example, a daily 8am job can pull the previous day's analytics and post a summary to your team channel; a weekly job can list links expiring in the next seven days for review. Because these jobs are idempotent and paced, cron plus the API gives you dependable automation without a separate scheduler platform. The webhooks and automation guide shows the end-to-end pattern these cron triggers drive.
Ultimately, a cron expression is a promise about the future: "this will run at these times." The parser is what lets you verify that promise before you rely on it. Verify the next occurrences, test safely, and keep the job idempotent, and your scheduled automation will behave exactly as scheduled.
Conclusion
This guide covered the practical essentials of cron parser cron jobs guide. Apply the discipline, test before relying on it, and revisit when your needs change.
