Cron Expression Calculator — Describe & Preview Any crontab Line

Type a 5-field cron expression, get a plain-English schedule and the next run times — real dom/dow OR semantics, names, ranges, steps, lists and @-shortcuts.

Next runs

    Build it field by field

    minute
    hour
    day of month
    month
    day of week

    Dialect: standard cron (Vixie/POSIX). ? is accepted in the two day fields; L, W and # are Quartz extensions and get an explicit error, not a silent guess.

    Common schedules

    expressionmeans
    * * * * *every minute
    */5 * * * *every 5 minutes
    0 * * * *hourly, at :00
    0 9 * * 1-5weekdays at 09:00
    30 2 * * *daily at 02:30
    */15 2-4 1 * *every 15 min, 02:00–04:45, on the 1st
    0 0 * * 0weekly, Sunday midnight
    0 0 1 * *monthly, on the 1st
    0 0 13 * 513th or Friday — the OR trap
    0 0 29 2 *Feb 29 — leap years only
    @dailynickname for 0 0 * * *
    @rebootonce at daemon startup

    Reading the five fields

    A crontab line is five fields — minute hour day-of-month month day-of-week — followed by the command. Each field takes * (every value), a single number, a comma list (1,15), a range (9-17), or a step (*/15, 2-30/5). The month field also takes JANDEC and the weekday field SUNSAT, plus 0 or 7 for Sunday. So 30 9 * * 1-5 is “at 09:30, Monday through Friday” — the expression this page opens with.

    Two rules surprise nearly everyone. First: when both day fields are restricted, standard cron fires when either matches — 0 0 13 * 5 runs on the 13th and every Friday, not “Friday the 13th”. Second: day-of-month values that don’t exist in a month are silently skipped — 31 never fires in February, and 29 fires only in leap years. The calculator applies both rules faithfully and flags them when they bite; the OR trap and the field reference go deeper.

    The honest caveats

    The next-run list is computed in your browser’s timezone, while a real daemon schedules in the server’s local time (or CRON_TZ where it’s supported). Around DST transitions the behavior of jobs in the skipped/duplicated hour is implementation-defined — some crons skip them, some run them late, some fire twice. And @reboot has no clock schedule at all: it fires at daemon startup, full stop.

    Expressions in the Quartz dialect (Spring, AWS EventBridge, some CI tools) add seconds, a year field, L/W/# — this calculator parses standard cron and says so when it meets Quartz syntax, instead of guessing wrong quietly.

    More depth: cron field reference · the dom/dow OR trap · debugging silent cron failures · systemd timers vs cron.

    Everything here runs in your browser — no upload, no server round-trip, works offline once loaded.

    Frequently asked questions

    Which cron dialect does this calculator use?

    Standard 5-field cron — the POSIX/Vixie dialect used by crontab on Linux, BSD and macOS (and by GitHub Actions). That means *, lists, ranges, steps, month/day names, and the classic OR rule between day-of-month and day-of-week. Quartz extensions (L, W, #, seconds/year fields) are rejected with an explicit message rather than silently misread — ? is the one Quartz-ism we accept, treated as *.

    Why does "0 0 13 * 5" run on the 13th AND every Friday?

    Because standard cron applies a logical OR between the two day fields when both are restricted — the job fires when either matches. It's the single most-misunderstood cron rule (Quartz schedulers use AND instead). The dom/dow trap article shows how to get "13th and Friday" when that's what you actually want.

    What does the ? character do?

    In Quartz-derived schedulers (AWS EventBridge, Spring, some CI systems) ? means "no specific value" and one of the two day fields must be ?. Standard cron doesn't know the character — we accept it as an alias for * so pasted Quartz expressions still read correctly, and say so on the result.

    Why can't it schedule "the last day of the month"?

    Because standard cron has no syntax for it — L is a Quartz invention. The portable workaround is a small guard in the command itself, e.g. 0 0 28-31 * * [ "$(date -d tomorrow +\%d)" = "01" ] && cmd. The field reference covers this and the W/# extensions.

    Whose timezone do the predicted times use?

    Your browser's — the page shows the zone name under the list. But that's the caveat: a real cron daemon fires in the server's local timezone (or CRON_TZ where supported). And around DST transitions, jobs in the skipped or duplicated hour behave differently across implementations — some skip, some run late, some fire twice. If your server is UTC and you are not, shift accordingly.

    Can a valid expression still never run?

    Yes — day-of-month overflow. 0 0 31 2 * asks for February 31st, which doesn't exist; the calculator detects that and says "never" instead of listing dates. 0 0 29 2 * is the subtle version: it runs, but only on leap years — including the 8-year gap across century years like 2100.

    Does anything I type get sent anywhere?

    No. The parser, the explainer and the next-run engine are plain JavaScript running in your tab — the page is a static file, works offline once loaded, and keeps no history of what you check. Details in the privacy policy.

    Latest articles