Skip to content

Crontab Generator & Cron Expression Builder

Build, validate, and decode cron expressions in your browser. Live next-run preview in local time or UTC. POSIX 5-field syntax, presets, plain-English description. Free, private, no signup.

No Tracking Runs in Browser Free
All parsing and next-run computation happen locally in your browser. No data is sent to any server.

Fields
Presets

Human-readable

Next 5 scheduled runs

Timezone for next-run preview
    Reviewed for POSIX 5-field compliance, OR-semantics correctness, step-operator anchoring, named-token expansion, and Quartz operator rejection with helpful errors — Go Tools Engineering Team · May 20, 2026

    What Is a Cron Expression?

    A cron expression is a five-field string that defines a repeating schedule. From left to right, the fields are minute (0-59), hour (0-23), day-of-month (1-31), month (1-12), and day-of-week (0-6, where 0 and 7 both mean Sunday). Each field accepts a value, a list (`1,3,5`), a range (`1-5`), a wildcard (`*` meaning any value), or a step (`*/15` meaning every 15). The combination defines exactly when the scheduled command will run — `0 9 * * 1-5` for example reads "at minute 0, hour 9, any day-of-month, any month, day-of-week Monday through Friday" — in plain English, "weekdays at 9:00 AM".

    Cron originated in Unix Version 7 in 1979 and the five-field grammar has remained essentially unchanged for over four decades — a testament to how well-designed the original syntax is. Today cron expressions are used far beyond the Unix crontab file: Kubernetes CronJobs, GitHub Actions workflows, AWS EventBridge rules, GitLab CI scheduled pipelines, Cloudflare Workers Cron Triggers, and serverless platforms across every cloud all accept the same five-field grammar. Learning cron once means knowing how to schedule jobs in every modern infrastructure context.

    The POSIX standard defines five operators: `*` (any value), `,` (list of values), `-` (range), `/` (step), and named tokens for months (JAN-DEC) and weekdays (SUN-SAT). Most implementations also expand five common shortcuts: `@yearly` (`0 0 1 1 *`), `@monthly` (`0 0 1 * *`), `@weekly` (`0 0 * * 0`), `@daily` (`0 0 * * *`), and `@hourly` (`0 * * * *`). The Quartz scheduler (a Java library) extends this with an optional seconds field and additional operators (`?`, `L`, `W`, `#`) — useful if you're working in Java/Spring, but not portable to standard cron. This tool follows the POSIX five-field standard because it's the dominant variant and the one your Linux server, GitHub Actions runner, and Kubernetes cluster will actually understand.

    One quirk of POSIX cron deserves special attention: when both day-of-month and day-of-week are restricted (neither is `*`), the schedule runs when EITHER matches — OR semantics, not AND. So `0 0 1 * 5` runs on the 1st of every month AND every Friday, not just Fridays that happen to fall on the 1st. This is the single most common cron surprise; the next-run preview in this tool makes it obvious by showing the actual datetimes the schedule will fire. Verify before deploying.

    All parsing and next-run computation happens entirely in your browser using JavaScript — no expressions, schedules, or any other data are ever sent to a server. This tool parses any standard POSIX cron expression instantly with a plain-English description and a five-run preview, with complete privacy.

    Cron expressions are closely related to other developer tools. Cron jobs are commonly debugged by checking Unix timestamps against the expected run times, and complex schedules are often documented as JSON configuration which can be validated with our JSON formatter. For an in-depth guide covering the OR semantics, timezone pitfalls, and common cron variants with examples in Linux, Kubernetes, and GitHub Actions, read our cron schedule reference.

    # Linux crontab entry — runs every 15 minutes
    */15 * * * *  /usr/local/bin/poll-api.sh
    
    # Kubernetes CronJob — weekdays at 9:00 AM UTC
    apiVersion: batch/v1
    kind: CronJob
    metadata:
      name: daily-report
    spec:
      schedule: "0 9 * * 1-5"
      timeZone: "UTC"
      jobTemplate:
        spec:
          template:
            spec:
              containers:
                - name: report
                  image: report-runner:1.0
              restartPolicy: OnFailure
    
    # GitHub Actions workflow — hourly
    on:
      schedule:
        - cron: '0 * * * *'
    
    # AWS EventBridge — first of each month
    ScheduleExpression: cron(0 0 1 * ? *)
    # (Note: AWS uses the Quartz 6-field form with '?' for day-of-week)

    Key Features

    Live POSIX 5-Field Parser

    Strict parser following POSIX cron: 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, with 7 also accepting Sunday). All standard operators (`*` `,` `-` `/`) and macros (`@yearly` `@monthly` `@weekly` `@daily` `@hourly`) supported.

    Next 5 Runs Preview

    Computes the next five scheduled run times from your current local time. Switch between Local and UTC with one click — the most reliable way to catch timezone surprises before deploying a crontab to a server in a different region.

    Plain-English Description

    Every valid expression gets a human-readable explanation: "Every 15 minutes", "Weekdays at 9:00 AM", "At 02:30 on day 1 of the month, in January and July". Makes code review and team handoff effortless — no more guessing what `*/5 9-17 * * 1-5` actually does.

    Field-Level Error Messages

    Invalid expressions get instant red feedback with the offending field highlighted and a specific error: "Error in minute: value out of range [0, 59]: "60"". No more silent crontab failures discovered three days later when the report didn't run.

    Preset Chips for Common Schedules

    Eleven one-click presets cover the schedules you'll actually use: every minute, every 5/15 minutes, every hour, daily at midnight or 9 AM, weekdays at 9 AM, weekly on Sunday/Monday, first of each month, and yearly. Tap, tweak, ship.

    Per-Field Builder Inputs

    Don't memorize the five-field order — five small inputs labeled Minute, Hour, Day of month, Month, Day of week let you edit one position at a time without dropping a value or mis-ordering. The full expression at the top rebuilds automatically.

    POSIX OR Semantics Done Right

    When both day-of-month and day-of-week are restricted, the OR rule kicks in — `0 0 1 * 5` runs every 1st AND every Friday. The next-run preview makes this visible before you deploy; no more surprise weekend pages.

    100% Browser-Based Privacy

    Your cron expressions — which often reveal infrastructure timing and internal scheduling patterns — never leave your browser. No data is sent to any server, no logging, no analytics. You can verify this in your browser's Network tab. Safe for production schedules and internal systems.

    Quartz-Aware Error Messages

    If you paste a Quartz expression with `?` `L` `W` or `#`, the parser explains "Quartz operators not supported — use POSIX syntax" so you know to rewrite for cron instead of debugging a silent failure. Quartz schedules don't run on Linux cron.

    Cron Variants & Schedulers

    Vixie cron (Linux default)

    5-field POSIX

    The default on most Linux distros. Strict POSIX with `CRON_TZ=` extension for explicit timezone. Day-of-month / day-of-week OR semantics apply. This tool's primary target.

    BSD cron

    5-field POSIX

    macOS and BSD-family default. POSIX-compatible with minor implementation differences from vixie cron; most expressions work identically.

    systemd timers (OnCalendar)

    calendar spec, not cron

    Alternative to cron on systemd-based Linux. Uses `OnCalendar: 2026-*-* 09:00:00` syntax — more readable for non-recurring schedules but not interoperable with cron expressions.

    Quartz Scheduler (Java/Spring)

    6 or 7 fields

    Adds seconds (mandatory) and year (optional) fields, plus operators `?`, `L`, `W`, `#`. Useful for Java apps but not portable to Linux cron.

    AWS EventBridge

    6-field Quartz-style with `?`

    Requires the day-of-week or day-of-month to be `?` (Quartz convention) rather than `*` when only one is restricted. Expressions don't port directly to Linux cron.

    Kubernetes CronJob

    5-field POSIX + timeZone field

    POSIX 5-field schedule plus `spec.timeZone` field (1.27+). Cleaner than relying on the kubelet's host timezone. Expressions port directly from Linux cron.

    GitHub Actions

    5-field POSIX

    Always runs in UTC. Best-effort timing — may be skipped under high load. Avoid intervals shorter than 15 minutes. Expressions port directly from Linux cron.

    Cron Expression Examples

    Every 15 Minutes

    */15 * * * *

    Step operator: `*/15` in the minute field means "every 15 minutes starting at minute 0" — so runs are at :00, :15, :30, :45 every hour of every day. The most common interval for polling APIs, refreshing caches, and heartbeat checks.

    Weekdays at 9:00 AM

    0 9 * * 1-5

    Range `1-5` in the day-of-week field means Monday through Friday (1=Mon, 5=Fri). Runs at exactly 09:00 — useful for business-hours reports, batch jobs that depend on overnight data, and daily standup reminders.

    First of the Month at Midnight

    0 0 1 * *

    Day-of-month `1`, all other lower fields zero. Common for monthly billing, log rotation, and end-of-period reconciliation. Day-of-month and day-of-week are both restricted only when neither is `*` — here day-of-week is `*` so only the day-of-month matters.

    Every 5 Minutes Between 9 AM and 5 PM, Weekdays

    */5 9-17 * * 1-5

    Combines step (`*/5`) with range (`9-17`) on different fields. Useful for business-hours-only monitoring or queue draining. Total: 12 runs/hour × 9 hours × 5 days = 540 runs per workweek.

    Quarterly: 1st of Jan, Apr, Jul, Oct at Midnight

    0 0 1 JAN,APR,JUL,OCT *

    Named months in a comma-separated list. Quarterly schedules like financial close, code-freeze reviews, or compliance audits. You can mix names and numbers (`1,APR,7,10` parses the same), but stick to one style for readability.

    POSIX OR Gotcha: 1st of Month OR Every Friday

    0 0 1 * 5

    When BOTH day-of-month (`1`) AND day-of-week (`5`) are restricted, POSIX cron runs the job if EITHER matches. So this fires on the 1st of every month AND every Friday — not just Fridays that fall on the 1st. This is the single most common cron surprise; the next-run preview makes it obvious.

    Every Day at 02:30 (Low-Traffic Window)

    30 2 * * *

    Specific values for both hour and minute, wildcards elsewhere. The 02:00-04:00 UTC window is the de facto convention for nightly batch jobs because it overlaps with no major business region's working hours. Pair with the UTC timezone toggle to confirm the run lands where you expect.

    Macro Equivalent: @daily

    @daily

    The `@daily` shortcut (also `@midnight`) expands to `0 0 * * *` — every day at midnight. Other macros: `@yearly` = `0 0 1 1 *`, `@monthly` = `0 0 1 * *`, `@weekly` = `0 0 * * 0`, `@hourly` = `0 * * * *`. Macros are concise but the five-field form is more portable across schedulers (e.g., some support macros, some don't).

    How to Build a Cron Expression

    1. 1

      Type or paste a cron expression

      Enter a five-field cron expression in the input above (e.g., `*/15 * * * *`). The tool parses and validates as you type — green check for valid, red error with field name for invalid. Macros like `@daily`, `@hourly`, etc. are also accepted.

    2. 2

      Or tweak the five field inputs

      Don't memorize the field order — edit Minute, Hour, Day-of-month, Month, or Day-of-week individually using the labeled inputs. The full expression at the top updates automatically. Use `*` for wildcards, `*/N` for steps, `a-b` for ranges, and `1,3,5` for lists.

    3. 3

      Pick a preset to jump-start

      Tap any preset chip (Every 15 minutes, Weekdays at 9 AM, etc.) to load a common schedule, then tweak the fields to fit your exact need. Eleven presets cover the patterns you'll actually use in production.

    4. 4

      Verify the next-run preview

      Look at the five upcoming run datetimes — switch between Local and UTC to confirm the schedule fires when you intend. This is the single most reliable way to catch the POSIX day-of-month / day-of-week OR gotcha before it bites you in production.

    5. 5

      Copy and paste into your scheduler

      Click Copy to grab the expression. Paste into your crontab, systemd timer, GitHub Actions `cron:`, AWS EventBridge, Kubernetes CronJob `schedule`, or any cron-compatible scheduler. Don't forget to verify the target scheduler's timezone — see the Best Practices section below.

    Common Cron Mistakes

    POSIX OR Trap: Both Day Fields Restricted

    When BOTH day-of-month and day-of-week are restricted, POSIX cron runs the job if EITHER matches — not both. So `0 0 1 * 5` fires on the 1st of every month AND every Friday, not just Fridays-that-fall-on-the-1st. Use `*` in one of the two day fields when you want a single condition, or write a wrapper script that does the AND check.

    ✗ Wrong
    # Intended: "first Friday of the month"
    0 0 1-7 * 5
    # Actually: fires on days 1-7 of the month OR every Friday — both conditions
    ✓ Correct
    # Use wrapper for true AND semantics
    0 0 * * 5  [ $(date +\%d) -le 7 ] && /your-script
    # OR drop one condition and accept the looser schedule

    Timezone Drift Between Dev and Prod

    Cron schedules on a Linux server use the system timezone, not the writer's local timezone. A 9:00 AM cron on a server set to UTC fires at 4:00 AM US East. Always design schedules against the target server's timezone — preferably UTC — and lock the timezone explicitly with `CRON_TZ=...` at the top of the crontab.

    ✗ Wrong
    # Written by US East dev, deployed to UTC server
    0 9 * * *  /your-report.sh
    # Fires at 9 AM UTC = 4 AM US East — not what the dev meant
    ✓ Correct
    # Lock timezone, or write in UTC explicitly
    CRON_TZ=America/New_York
    0 9 * * *  /your-report.sh

    Step Operator Confusion: '*/15' vs '15'

    `*/15` in minute means "every 15 minutes starting at 0" (so 0, 15, 30, 45). Just `15` means "only at minute 15" — one run per hour. Beginners frequently write `15` thinking it's every 15 minutes; the tool's plain-English description makes the mistake obvious before deploy.

    ✗ Wrong
    # Intended: every 15 minutes
    15 * * * *
    # Actually: once per hour, at minute 15 (4 runs/hour less than intended)
    ✓ Correct
    # Correct
    */15 * * * *
    # Every 15 minutes: minute 0, 15, 30, 45 of every hour

    Six-Field Expression on POSIX Scheduler

    Quartz/Spring/node-cron support an optional seconds field as the first position. Linux crontab, GitHub Actions, AWS EventBridge (mostly), and Kubernetes CronJob do NOT — they expect five fields. Pasting a six-field expression silently breaks the schedule: your seconds become minutes, minutes become hours, etc.

    ✗ Wrong
    # Quartz 6-field copied into Linux crontab
    0 0 9 * * 1-5
    # Linux reads: minute=0, hour=0, dom=9, month=*, dow=1-5
    # = midnight on days 9 in months matching weekdays — chaos
    ✓ Correct
    # POSIX 5-field, drop the seconds
    0 9 * * 1-5
    # = weekdays at 9:00 AM

    Day-of-Month Out of Range for Month

    Cron does not validate day-of-month against the actual month. `0 0 31 2 *` (February 31st) parses fine but never matches — February has at most 29 days. Beginners assume the parser will catch this; it doesn't. The next-run preview in this tool shows "No upcoming runs" when an expression is structurally valid but logically impossible.

    ✗ Wrong
    # February 30 or 31 — never runs
    0 0 30 2 *
    0 0 31 2 *
    # Parses but no schedule ever fires
    ✓ Correct
    # Use day-of-week 'last weekday of February' pattern via script
    0 0 28-29 2 *  [ $(date -d tomorrow +\%m) = 03 ] && /your-script

    Mistaking Quartz Syntax for POSIX

    AWS docs, Spring tutorials, and many Stack Overflow answers show Quartz cron expressions with `?`, `L`, `W`, or `#`. These don't work in Linux crontab. If you copy a six-field expression with `?` in the day-of-week slot, the Linux parser will reject it (or worse, silently misparse). This tool catches Quartz operators and explains the difference.

    ✗ Wrong
    # Quartz: 'last Friday of the month' — invalid in POSIX
    0 0 ? * 6L *
    ✓ Correct
    # POSIX wrapper script approach for last-Friday
    0 0 25-31 * 5  /your-script
    # Run on Friday between the 25th-31st of any month

    Common Use Cases

    Linux Crontab Jobs
    Build and verify entries for `/etc/crontab`, `/etc/cron.d/*`, or per-user `crontab -e` files. Use the next-run preview to confirm the schedule lands at the right time in your server's configured timezone before saving.
    Kubernetes CronJob Schedules
    Generate the `spec.schedule` field for a Kubernetes CronJob. Kubernetes 1.27+ also supports `spec.timeZone` — use the UTC toggle to design your schedule in UTC, then explicitly set `timeZone` to avoid the worker node's local time.
    GitHub Actions Scheduled Workflows
    Build the `cron:` entry under `on.schedule`. GitHub Actions runs in UTC always — toggle the preview to UTC to confirm your schedule. Avoid intervals shorter than 15 minutes; GitHub's scheduler skips short-interval jobs under load.
    AWS EventBridge Rules
    Compose the cron expression for an EventBridge scheduled rule. Note: AWS uses Quartz-style six-field syntax with `?` for day-of-week — this tool emits POSIX five-field, which you'll need to convert by prefixing seconds (`0`) and replacing the `*` in either day field with `?`.
    GitLab CI Scheduled Pipelines
    Verify the cron expression for a scheduled CI pipeline in GitLab. GitLab uses POSIX five-field syntax — what this tool emits — and a UI date picker, but the cron form gives you finer control for non-standard intervals.
    Cloudflare Workers Cron Triggers
    Build the `[triggers.crons]` entry in `wrangler.toml`. Cloudflare uses POSIX five-field syntax. Minimum interval is one minute; the worker runs at UTC. Use the preview to verify the trigger fires within your expected window.
    Node.js node-cron Schedules
    Build expressions for the `node-cron` library, which supports both five-field POSIX and an optional leading seconds field. Stick to five fields unless you specifically need sub-minute precision — six-field expressions don't port to Linux crontab.
    Code Review and Documentation
    Paste a cron expression from a PR or runbook to instantly see what it does — no more guessing at `30 7 * * 1-5` or pulling out a reference card. The plain-English description is also great for inline comments and README files.

    Cron Syntax Reference

    Field Order: M H D M W
    Minute (0-59), Hour (0-23), Day-of-month (1-31), Month (1-12), Day-of-week (0-6, 7 also = Sunday). Mnemonic: "My Hat Doesn't Match Wendy's". The day-of-week field accepts both numeric (0-6) and named (SUN-SAT, case-insensitive) tokens.
    Operators
    `*` = any value; `,` = list separator (`1,3,5`); `-` = range (`1-5`); `/` = step (`*/15`, `5/10`); names: JAN-DEC for month, SUN-SAT for day-of-week (case-insensitive).
    Macros (Aliases)
    `@yearly` = `0 0 1 1 *`; `@annually` = `0 0 1 1 *`; `@monthly` = `0 0 1 * *`; `@weekly` = `0 0 * * 0`; `@daily` = `0 0 * * *`; `@midnight` = `0 0 * * *`; `@hourly` = `0 * * * *`. `@reboot` is a special non-schedule (runs only at boot) and is rejected with an explanatory error.
    POSIX Day Semantics (OR Rule)
    When BOTH day-of-month and day-of-week are restricted (neither is `*`), the schedule runs when EITHER matches — OR semantics. When only one is restricted, that one decides. When both are `*`, every day matches. This OR rule applies to vixie cron, BSD cron, and most POSIX implementations; Quartz uses `?` to disambiguate AND vs OR.
    Six-Field Mode (Quartz-Lite)
    If your input has six space-separated tokens, the tool treats the first as a seconds field (0-59). Useful for Quartz, Spring `@Scheduled(cron=...)`, and node-cron. NOT portable to Linux crontab or POSIX schedulers — they'd treat your seconds as minutes and shift everything by one position.
    Step Operator Anchoring
    `*/N` is anchored to the field's lowest value: `*/15` in minute = `0,15,30,45`, not "every 15 starting now". With a non-wildcard base: `5/15` in minute = `5,20,35,50`. Step values that don't divide the field range evenly will skip near the wraparound — this is correct, not a bug.
    Validation Boundaries
    minute ∈ [0,59], hour ∈ [0,23], day-of-month ∈ [1,31], month ∈ [1,12], day-of-week ∈ [0,7]. Out-of-range values produce a field-level error. The day-of-month is NOT validated against the month (`0 0 31 2 *` parses fine but never matches because Feb has no day 31 — the next-run preview will show "No upcoming runs").
    Quartz Operators Rejected
    POSIX cron does not support Quartz's `?` (no specific value), `L` (last), `W` (nearest weekday), or `#` (nth weekday). This tool rejects them with a clear "Quartz operators not supported" message rather than silently parsing them as invalid POSIX. For Quartz schedules, use a Quartz-aware tool or the Spring scheduler instead.
    Year-Cap on Next-Run Search
    The next-run computation searches up to 4 years forward; expressions that match less often than that (e.g., "Feb 29" patterns) will show "No upcoming runs in the next 4 years". This is by design to avoid unbounded iteration on impossible patterns.

    Best Practices for Cron Schedules

    Use UTC on Servers, Convert at Display Time
    Set your servers to UTC (`/etc/timezone` or `TZ=UTC`) and write all cron expressions in UTC. Convert to local time only at display time in your dashboards and reports. This eliminates an entire category of timezone bugs that hit hardest during daylight-saving transitions, when local-time schedules silently double-fire or skip a run. Use the UTC toggle in this tool to design your schedule in UTC from the start.
    Avoid the POSIX Day-of-Month/Day-of-Week OR Trap
    Never restrict both day-of-month AND day-of-week unless you want OR semantics. If you want "every Monday in January", write `0 0 * 1 1` (day-of-month is `*`); if you want "the 1st of every month", write `0 0 1 * *` (day-of-week is `*`). The POSIX OR rule means `0 0 1 * 1` runs on the 1st AND every Monday — almost certainly not what you intended. The next-run preview will catch this if you check before deploying.
    Lock the Schedule's Timezone Explicitly
    Modern schedulers support pinning the timezone in the schedule definition: `CRON_TZ=America/New_York` at the top of a crontab (vixie cron 3.0+), `spec.timeZone: "America/New_York"` for Kubernetes CronJobs 1.27+, schedule expression with `ScheduleExpressionTimezone` for AWS EventBridge Scheduler. Lock the timezone explicitly rather than relying on the server's default — server timezones can change without warning during infrastructure migrations.
    Spread Load Across Minutes, Not at :00
    Avoid `0 * * * *` (every hour at minute 0) for non-critical jobs — at scale, scheduling many things at exactly :00 creates load spikes. Pick a random minute offset (`23 * * * *`, `41 * * * *`) for each job to spread load. The same applies for daily jobs: `30 3 * * *` is friendlier to your database than `0 3 * * *` when many jobs converge at 3:00.
    Make Jobs Idempotent
    Cron has no built-in retry, no overlap prevention, no missed-run recovery. Your job should be safe to run multiple times (idempotent) and self-checking. Instead of "send report at 9 AM", design it as "send today's report if not already sent" — this self-heals after downtime, accidental double schedules, and concurrent runs. Idempotency is a property of the job, not the scheduler, and it's the single most important reliability practice.
    Add a Heartbeat for Critical Schedules
    Cron's silent failure mode is its biggest weakness — if the schedule doesn't fire, nothing tells you. For critical jobs, have the job ping a heartbeat service (Healthchecks.io, Cronitor, Dead Man's Snitch) at the end of each run; the service alerts you if the expected ping doesn't arrive. This catches both the job failing and the schedule itself misfiring. Free tier covers most personal and small-team needs.
    Verify with the Next-Run Preview Before Shipping
    Before deploying a new cron schedule, look at the five upcoming run datetimes in this tool's preview. Toggle between Local and UTC. Confirm the schedule lands when you intend — not five minutes early, not on the wrong day, not skipping the weekend you cared about. The preview is the cheapest possible production test.

    Frequently Asked Questions

    What does this tool do?
    It parses, validates, and explains cron expressions in your browser, with a live preview of the next five scheduled runs in your timezone or UTC. Type any standard POSIX five-field cron expression — or use the preset chips and per-field inputs to build one without memorizing the syntax — and the tool produces a plain-English description ("Every 15 minutes", "Weekdays at 9:00 AM", etc.) plus the actual datetimes when the job will fire. Wrong expressions are caught instantly with a field-level error message so you don't waste a deploy on a broken schedule. The whole tool runs 100% client-side: nothing is uploaded, logged, or stored — safe for production crontabs and internal schedules with sensitive timing patterns.
    What is a cron expression?
    A cron expression is a five-field string that defines a repeating schedule. The fields are minute (0-59), hour (0-23), day-of-month (1-31), month (1-12), and day-of-week (0-6, where 0 and 7 both mean Sunday). Each field accepts a value, a list (`1,3,5`), a range (`1-5`), a wildcard (`*` = any), or a step (`*/15` = every 15). The combination of all five fields defines exactly when the scheduled command should run. Cron originated in Unix V7 (1979) and remains the de facto language for time-based job scheduling on Linux/Unix, in container orchestration (Kubernetes CronJobs), in CI/CD (GitHub Actions, GitLab CI), and in serverless platforms (AWS EventBridge, Cloudflare Workers Cron Triggers). Despite many alternatives proposed over the decades, no replacement has displaced cron's terse, expressive five-field grammar.
    Is my data uploaded anywhere?
    No. All parsing, validation, and next-run computation runs 100% client-side in your browser using JavaScript. Your expressions are never transmitted, never stored on any server, never logged, and never analyzed. This makes the tool safe for production crontabs, internal scheduling patterns that reveal infrastructure timing, and any sensitive schedules. You can verify this in your browser's Network tab — typing a cron expression triggers zero network requests. The tool uses no cookies for input data and no third-party analytics that would capture what you type.
    What's the difference between POSIX cron and Quartz?
    POSIX cron is the five-field standard used by Unix/Linux crontab, systemd timers, GitHub Actions, GitLab CI, AWS EventBridge, Kubernetes CronJobs, and most schedulers. Quartz is a Java scheduling library that adds a seconds field (six or seven fields total) plus extra operators: `?` (no specific value, used when day-of-month and day-of-week conflict), `L` (last — last day of month, last Friday, etc.), `W` (nearest weekday), and `#` (nth weekday of month, e.g., `2#1` = first Tuesday). This tool implements POSIX cron because it's far more widely used; Quartz operators are reported as syntax errors with a clear "Quartz operators not supported" message. If you need Quartz, popular Java schedulers like Quartz Scheduler and Spring's `@Scheduled` are your target — but the schedule definitions don't port directly to Linux cron.
    Why does '0 0 1 * 5' run on every Friday AND the 1st?
    This is POSIX cron's day-of-month / day-of-week OR semantics, and it's the single most common cron surprise. The rule: when BOTH fields are restricted (neither is `*`), cron runs the job if EITHER condition matches — not both. So `0 0 1 * 5` (day-of-month=1, day-of-week=5) fires on the 1st of every month AND every Friday, not just Fridays that happen to fall on the 1st. If you wanted only the latter (AND semantics — Friday-the-1st), you can't express it in standard cron; you'd need a script that runs every Friday OR the 1st and exits early based on the actual date. Vixie cron (the GNU/Linux default), BSD cron, and AWS EventBridge all follow this OR rule. The next-run preview in this tool makes the actual schedule obvious — paste suspicious expressions and verify before deploying.
    How do I run a job every 30 seconds?
    You can't, with standard POSIX cron. Cron's minimum granularity is one minute — the smallest field is minute (0-59). For sub-minute schedules, your options are: (1) Run two jobs at `* * * * *` and `* * * * *` with `sleep 30 &&` in front of one — crude but works for vixie cron. (2) Use a scheduler with seconds support like Quartz, Kubernetes CronJob with a custom controller, or systemd timers with `OnCalendar: *-*-* *:*:00/30`. (3) Run a long-lived daemon that sleeps 30 seconds between iterations — the right answer for most monitoring needs. (4) Switch to an event-driven trigger (webhook, message queue) if you actually need real-time response. The 30-second cron pattern is almost always a sign that cron is the wrong abstraction.
    What timezone does cron use?
    On a Linux server, vixie cron uses the system timezone — usually set via `/etc/timezone` or the `TZ` environment variable. This is a frequent source of bugs: a 9:00 AM cron on a US East server fires at 14:00 UTC, but on a server set to UTC it fires at 09:00 UTC (i.e., 4:00 AM East). The fix is either to always set your servers to UTC and write all cron expressions in UTC, or to set the `CRON_TZ=America/New_York` variable at the top of the crontab to pin the timezone explicitly (supported by vixie cron 3.0+). Managed schedulers vary: GitHub Actions runs UTC always, AWS EventBridge supports timezone in the schedule definition, Kubernetes CronJob added a `spec.timeZone` field in 1.27+. This tool's UTC/Local toggle lets you preview the schedule in either timezone — flip between them to confirm the run lands where you intended.
    What does '*/15' actually expand to?
    The step operator `*/N` means "every N starting at the lowest valid value of the field". For minute (range 0-59), `*/15` expands to `0,15,30,45` — four runs per hour at the quarter-hour. The step is NOT "every 15 minutes from the current time"; it's anchored to the field's starting value. Same logic for other fields: `*/2` in hour means `0,2,4,...,22` (12 runs); `*/3` in day-of-month means `1,4,7,...,31` (11 runs). For non-wildcard step bases (e.g., `5/15`), the expansion is from the base: `5/15` in minute = `5,20,35,50`. Step values that don't divide the range evenly will skip near the wraparound — this is correct cron behavior, not a bug. The next-run preview makes the actual schedule obvious.
    Can I use a six-field expression with seconds?
    Six-field expressions with a leading seconds field (range 0-59) are a Quartz/Spring/Cron4j extension, not POSIX. This tool accepts six-field expressions when the input has exactly six space-separated tokens — useful if you're targeting Quartz, Spring `@Scheduled(cron=...)`, or Node.js libraries like `node-cron` that support seconds. For standard POSIX schedulers (Linux crontab, GitHub Actions, AWS EventBridge, Kubernetes CronJob), stick to five fields — adding a leading seconds field will silently break the schedule (the scheduler will interpret your minute as seconds, your hour as minute, etc., shifting everything by one). When in doubt, check your target scheduler's docs; if it doesn't explicitly say "six-field with seconds is supported", use five fields.
    What's the maximum interval cron can express?
    Without external state, cron can express up to once-per-year reliably with `0 0 D M *` (e.g., `0 0 1 1 *` = every January 1st at midnight). For "every two years" or longer intervals, cron alone is not enough — you'd need an external date check at the top of your script (e.g., `[ $(($(date +%Y) % 2)) -eq 0 ] && /your-command` to run on even years). For "every 90 days" or other non-aligned multi-day intervals, cron also fails: there's no native modulo-day operator, so you'd write a wrapper that checks the day-of-year against a reference date. If your scheduling needs are this complex, consider a real workflow scheduler (Airflow, Temporal, AWS Step Functions) — cron's grammar is intentionally simple and breaks down for anything beyond regular weekly/monthly patterns.
    How do I handle missed runs after downtime?
    Standard cron has no recovery — if the system was down at the scheduled time, the run is simply skipped. There's no log of "we missed this one". For critical jobs, you have three options: (1) Use `anacron` (or `systemd-cron` with `Persistent=true`), which catches up missed jobs after boot, suitable for laptops and intermittent systems. (2) Switch to a scheduler with built-in retry: Kubernetes CronJobs have `startingDeadlineSeconds` (run if delay is within deadline) and `concurrencyPolicy` (avoid overlapping runs); AWS EventBridge supports retry policies. (3) Build idempotency into the job itself: instead of "run report at 9 AM", have the job query "has today's report been generated?" and produce it if not — this self-heals after any downtime length. Option 3 is the most robust and works with any scheduler.
    Why is my GitHub Actions cron not running on time?
    GitHub Actions schedules are best-effort: they can fire up to several minutes late under high load on GitHub's infrastructure, and during very high load they may be skipped entirely (especially for short intervals like every five minutes). The same disclaimer applies to most managed schedulers — they trade exact timing for scale and reliability. Practical implications: (1) Don't schedule things that must run at an exact second; cron is for "roughly at this time, daily". (2) For short intervals, prefer a long-lived worker over a scheduled job. (3) For exact-time financial or compliance cutoffs, use a dedicated cron daemon on a server you control, or a stricter scheduler like AWS EventBridge Scheduler with the Standard schedule. (4) GitHub Actions specifically: avoid intervals shorter than 15 minutes; the scheduler will often skip them under load.

    Related Tools

    View all tools →