Cron Expression Generator & Explainer
Build a cron expression from a preset or by hand, read it back as a sentence, and see the next times it actually runs.
30 3 * * 1
# at 03:30 on Monday
# Next runs are worked out in your browser, against your clock.
# WordPress cron is not this. WP-Cron runs on page requests, so a site with no
# visitors runs nothing. To use real cron, disable WP-Cron in wp-config.php with
# define( 'DISABLE_WP_CRON', true ); and add:
# 30 3 * * 1 cd /path/to/site && wp cron event run --due-now
Output is valid and updates as you type.
Fix the highlighted fields to update the output.
Build a cron expression, read it back in plain English, and see the next times it will actually run.
How to use
- Start with a preset. It fills the fields, and you can then edit them.
- Read the sentence under the expression. If it does not say what you meant, the expression does not either.
- Check the next runs. They are worked out in your browser against your clock, in UTC, which is usually the fastest way to spot an off-by-one.
- Keep the WordPress note if this is for a WordPress site. WP-Cron is not cron, and the note shows how to hand the schedule to the real thing.
Example
30 3 * * 1
# at 03:30 on Monday
# Next runs, in UTC
2026-09-28 03:30 UTC
2026-10-05 03:30 UTC
2026-10-12 03:30 UTC
The five fields are minute, hour, day of month, month, day of week, in that order. * means every value of that field.
Pitfalls
- When both day of month and day of week are restricted, cron runs when either matches, not both.
0 0 13 * 5is the 13th and every Friday, which is why Friday the 13th jobs are a classic bug. The explainer spells this out. - Cron runs in the server’s timezone, and daylight saving makes a 02:30 job run twice or not at all on the two changeover days. Anything that matters belongs at a time that exists all year, or in UTC.
- WP-Cron is triggered by page requests. A site with no visitors runs nothing, and a site with many runs it late. Disabling WP-Cron and calling
wp cron event run --due-nowfrom real cron is the fix. - A job that overruns its schedule starts again anyway. Two copies of the same import running at once is the usual result; a lock file or a
flockwrapper prevents it. - Cron gives you almost no environment: no PATH to speak of, no shell profile, a different working directory. Use absolute paths and
cdfirst, which is what the WordPress line here does. - Output goes to mail, and mail usually goes nowhere. Redirect to a log or you will never know why it stopped working.
*/7does not mean “every seventh minute across the hour boundary”. It restarts at 0 each hour, so the gap between 56 and the next 0 is four minutes.- Seconds are not a cron field in standard crontab. Six field expressions belong to other schedulers, and a five field parser will reject them.
Compatibility
The five field syntax, ranges, lists, steps and the three letter month and day names are standard crontab(5), understood by Vixie cron, cronie, busybox and macOS. @reboot and the other nicknames are also widely supported but are not expressions, so they are not generated here. The next runs are computed in UTC to keep them unambiguous; your server’s crontab uses its own timezone.
Frequently asked questions
Why does my WordPress schedule not run on time?
How do I run something every 30 seconds?
What is the difference between 0 and 7 for Sunday?
Is */5 the same as 0,5,10,15…?
Which timezone do the next runs use?
timedatectl or date.