epochkit

Cron Expression Generator

Build and validate cron expressions.
Visual editor, presets, natural language input, and next-run preview.

Visual builder

MIN
HR
DOM
MON
DOW

Presets

Human description

At 09:00 AM, only on Monday

Next 5 runs
  1. 2026-05-11 09:00:00 UTC
  2. 2026-05-18 09:00:00 UTC
  3. 2026-05-25 09:00:00 UTC
  4. 2026-06-01 09:00:00 UTC
  5. 2026-06-08 09:00:00 UTC

Code snippets

GitHub Actions
name: Scheduled workflow
on:
  schedule:
    - cron: '0 9 * * 1'
  workflow_dispatch:

jobs:
  scheduled:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Run job
        run: echo "Running scheduled job"
  • • Workflows scheduled at the top of the hour may be delayed during high-load periods. Consider scheduling 5 minutes past the hour (e.g. "5 * * * *") for more reliable timing.
  • • Scheduled workflows run only on the default branch.
  • • Public repos: workflow auto-disabled after 60 days of no activity.
  • • workflow_dispatch added for manual testing — a common community pattern that lets you trigger the workflow manually without waiting for the next scheduled run.

Field reference

Field Allowed values
Minute 0–59
Hour 0–23
Day of month 1–31
Month 1–12
Day of week 0–6 (Sun=0)
* Every value
, List (0,15,30)
- Range (1-5)
/ Step (*/5)

How to use

1

Build your expression

Use the visual builder, click a preset, or type an expression directly. You can also try natural language like "every monday at 9am."

2

Verify the schedule

Read the human description and check the next 5 run times in your timezone. Change the timezone selector to see run times in different regions.

3

Copy a code snippet

Switch between GitHub Actions, Kubernetes, Vercel, and crontab tabs to get the platform-specific snippet. Click to copy.

Understanding cron expressions

A cron expression is a string of five fields that define when a scheduled task should run. Reading left to right: minute (0–59), hour (0–23), day of month (1–31), month (1–12), and day of week (0–6, where 0 is Sunday). The asterisk means "every" — so * * * * * runs every minute, and 0 9 * * 1 runs at 9:00 AM every Monday.

The special characters extend the basic notation significantly. The slash ( /) creates step values: */15 in the minute field means every 15 minutes. The comma ( ,) creates lists: 1,15 in the day-of-month field means "on the 1st and 15th." The hyphen ( -) creates ranges: 1-5 in the day-of-week field means Monday through Friday.

Every major platform uses the same five-field format, but timezone handling and constraints differ significantly. GitHub Actions defaults to UTC and supports a timezone field with any IANA timezone name; schedules shorter than 5 minutes are silently ignored, and adding workflow_dispatch alongside schedule is a common pattern that allows triggering the workflow manually. Kubernetes CronJobs pick up the kube-controller-manager local timezone by default; since Kubernetes 1.27 the timeZone field (camelCase) is stable — and unlike crontab, embedding CRON_TZ in the schedule string causes a validation error. Vercel Cron always runs in UTC with no timezone field; Hobby plan cron jobs may run at most once per day, and failed invocations are never retried, so handlers should be idempotent. Traditional crontab uses the system timezone and can be overridden with a CRON_TZ= directive (vixie-cron / cronie) or the TZ environment variable. The code snippet section above generates platform-ready configuration, including timezone fields, for each environment.

Frequently asked questions

What is a cron job?
A cron job is a scheduled task that runs automatically at specified intervals on a Unix-like system. The name comes from "cron," the time-based job scheduler in Unix. Cron jobs are commonly used for tasks like database backups, report generation, cache clearing, and sending scheduled emails. Each job is defined by a cron expression that specifies when it should run.
How do I read a cron expression?
A cron expression has five fields separated by spaces: minute (0-59), hour (0-23), day of month (1-31), month (1-12), and day of week (0-6, where 0 is Sunday). The asterisk (*) means "every" for that field. For example, "0 9 * * 1" means "at 09:00 on every Monday." The human-readable description on this page translates any expression automatically.
What is the difference between * and ? in cron expressions?
The asterisk (*) matches every value for a field. The question mark (?) is used in some cron systems (like Quartz) to indicate "no specific value" for the day-of-month or day-of-week field — because both cannot be set at the same time. Standard Unix cron does not use ?. If you see a ? in a cron expression, you are likely working with a Java or enterprise scheduler.
How do I run a cron job every 5 minutes?
Use the */5 notation in the minute field: "*/5 * * * *". The slash notation means "every N units." So */5 in the minute field means every 5 minutes, */2 in the hour field means every 2 hours, and so on. You can also list specific minutes: "0,5,10,15,20,25,30,35,40,45,50,55 * * * *" is equivalent but more verbose.
Why does my cron job not run?
Common causes: (1) The cron daemon is not running — check with "systemctl status cron" or "crontab -l". (2) The expression is invalid — paste it into this tool to validate it. (3) The command path is wrong — cron runs with a minimal environment, so use absolute paths. (4) Timezone mismatch — cron uses the system timezone, not your local timezone. (5) Permissions — the user running cron may not have execute permission on the script.
What is the difference between cron syntax in Vercel, GitHub Actions, Kubernetes, and crontab?
All four platforms use the standard 5-field cron syntax, but their timezone handling and constraints differ significantly. GitHub Actions defaults to UTC and supports the timezone field with an IANA timezone name. Minimum interval is 5 minutes — shorter schedules are ignored. Scheduled workflows run only on the default branch and may be delayed during high-load periods. Shorthand macros (@hourly, @daily) are not supported. Kubernetes CronJobs default to the kube-controller-manager local timezone. Use the timeZone field (Kubernetes 1.27+ stable) to specify an IANA timezone. CRON_TZ or TZ inside the schedule string is rejected with a validation error. Shorthand macros are supported. Vercel Cron always runs in UTC and does not support timezone configuration. Hobby plan: max once per day, invocation occurs within the specified hour. Pro plan and above: minute-level precision. Vercel does not retry failed invocations and may deliver duplicate events — design handlers to be idempotent. crontab uses the system timezone by default. Use the CRON_TZ directive (vixie-cron, cronie) or the TZ environment variable to override. Shorthand macros and @reboot are supported.

Learn more

Other tools you might find useful