Cron Expression Explainer & Generator
Bidirectional: write '0 9 * * 1-5' and get 'weekdays at 09:00' — or convert natural language to cron syntax.
How it works
- 1Pick directionExplain cron or generate from text.
- 2InputCron expression or natural-language description.
- 3ExplainAI responds in seconds.
Cron expressions in plain English: a deeper look at the 5- and 6-field formats
What cron actually is, and where it lives
Cron is the venerable Unix scheduler, introduced in V7 Unix (1979). The format is a single-line specification of when a command should run. Despite being 45 years old, it's still the most widely used scheduler — POSIX cron, GNU mcron, Vixie cron, systemd timers, Quartz (Java), Spring scheduling, GitHub Actions, Vercel Cron, AWS EventBridge: they all speak some flavor of cron syntax.
The format is dense by design. '0 9 * * 1-5' means 'at minute 0 of hour 9, every day-of-month, every month, on days-of-week 1 through 5 (Mon-Fri)' — i.e. 9:00 AM on weekdays. Five fields, separated by spaces. Each can be a value, range (1-5), list (1,3,5), step (*/15), or wildcard (*).
The five (or six) fields
Standard POSIX cron has five fields: minute (0-59), hour (0-23), day-of-month (1-31), month (1-12 or JAN-DEC), day-of-week (0-7 where 0 and 7 both mean Sunday, or SUN-SAT). Quartz cron (used by Spring, AWS) adds a seconds field at the start, making it six. Some dialects add a year field, making it seven.
When you copy a cron expression from documentation, the first thing to check is which dialect: 5-field (standard cron) or 6-field (Quartz). The same '0 9 * * 1-5' means '9:00 AM Mon-Fri' in standard cron, but in Quartz it means '0 seconds, hour 9, every minute, every day-of-month, January, every day-of-week' — completely different.
The day-of-month / day-of-week ambiguity
The two day fields interact in a non-obvious way. If both day-of-month and day-of-week are specified (non-wildcard), Vixie cron treats them as an OR: the job runs when EITHER matches. Other implementations (Quartz, BSD cron) treat them as AN AND. So '0 9 1 * 1' means 'either the 1st of the month OR every Monday' in Vixie, vs 'the 1st of the month AND it has to be a Monday' in Quartz.
This is a known footgun. Best practice: use '?' instead of '*' in one of the two fields to make the intent explicit (Quartz supports this; Vixie does not). Failing that, document which day field you mean and leave the other as '*'.
Step values: '*/5' and the underspecified case
'*/5' in the minutes field means 'every 5 minutes starting from minute 0' — so 0, 5, 10, 15, ..., 55. NOT 'every 5 minutes from when you started the cron daemon'. This trips people up: '*/15' in the hours field doesn't mean 'every 15 hours' (that would be impossible in a 24-hour clock) — it means '0, 15, 30, 45' which clips to '0, 15' since 30 and 45 are out of range.
To run something every 15 minutes regardless of clock alignment, you'd use systemd timers or a job queue, not cron. Cron is fundamentally clock-aligned.
Special strings: @hourly, @daily, @reboot
Most cron daemons accept named shortcuts: @hourly = '0 * * * *', @daily = '0 0 * * *', @weekly = '0 0 * * 0', @monthly = '0 0 1 * *', @yearly = '0 0 1 1 *'. @reboot runs once when the daemon starts. @midnight is a synonym for @daily.
@reboot is implementation-specific and not portable. Vercel Cron, AWS EventBridge, and GitHub Actions don't support it. systemd timers have their own equivalent (OnBootSec=). When converting cron expressions across environments, watch for non-portable features.
Time zone considerations
Cron runs in the time zone of the cron daemon. On Linux, that's typically /etc/timezone or the TZ environment variable. On managed cron services, time zone varies: Vercel Cron runs in UTC always, AWS EventBridge defaults to UTC, GitHub Actions runs in UTC. systemd timers can be configured per-timer.
Daylight saving transitions add complexity: a job scheduled for '0 2 * * *' will run twice on the day clocks fall back (once at 2 AM CET, once at 2 AM CEST), and skip on the day clocks spring forward (no 2 AM that day). The pragmatic fix: schedule sensitive jobs at 3 AM or later to avoid the ambiguous DST window.
When to use cron vs. alternatives
Cron is right for: simple, time-based, single-shot jobs (nightly backup, weekly report, periodic cache refresh). It's wrong for: workflows that need ordering or dependencies (use a workflow engine), jobs that must run exactly once across multiple servers (use a distributed lock or queue), or anything event-driven (use a message queue).
Modern alternatives: systemd timers (better logging, dependency support), Airflow / Temporal / Prefect (workflow orchestration with retries and observability), serverless cron (AWS EventBridge, Vercel Cron — managed, no machine to maintain). For simple scheduling, classic cron is still hard to beat for operational simplicity.
Frequently asked
Which cron formats are supported?
Standard POSIX 5-field plus 6-field (Quartz / systemd) with seconds.
Get new tools first.
One tool per week. No ads. Unsubscribe anytime.