Home/Blogs/Developer Tools Guide

Cron Expression Generator — How to Write, Understand & Test Cron Schedules Free (2026)

·11 min read

The complete 2026 guide to cron expressions — the 5-field syntax explained field by field, every special character with examples, 30+ ready-to-use schedules, timezone gotchas, and the free online Cron Expression Generator that builds and validates cron syntax in real time.

Cron expressions are one of those things that look intimidating the first time you encounter them — five or six cryptic fields of asterisks, numbers, and slashes — and then become obvious the moment someone explains the pattern. The free Cron Expression Generator lets you build any cron schedule visually and shows the next 10 run times instantly so you can confirm it does what you expect before it goes anywhere near a production server. This guide explains everything: the syntax field by field, every special character with practical examples, 30+ ready-to-use expressions, timezone gotchas, and the differences between Linux crontab, Kubernetes CronJobs, AWS EventBridge, and GitHub Actions schedules.

The 5-Field Cron Syntax — Explained Once and for All

A standard cron expression has five fields, separated by spaces:

┌───────── minute        (0 - 59)
│ ┌─────── hour          (0 - 23)
│ │ ┌───── day of month  (1 - 31)
│ │ │ ┌─── month         (1 - 12 or JAN-DEC)
│ │ │ │ ┌─ day of week   (0 - 7 or SUN-SAT, 0 and 7 are both Sunday)
│ │ │ │ │
* * * * *

The cron daemon (or scheduler) checks the current time against every field. The job runs only when all five fields match simultaneously. An asterisk in any field means "match everything" — any value for that field is accepted. This is why * * * * * runs every minute: every possible value matches every field.

Field 1: Minute (0–59)

Controls which minute(s) within an hour the job runs.

Value Meaning
0At the top of the hour (minute zero)
30At the half-hour mark
*/15Every 15 minutes (at 0, 15, 30, 45)
0,30At minute 0 and minute 30 (twice per hour)
10-20Every minute from the 10th to the 20th

Field 2: Hour (0–23)

Controls which hour(s) the job runs. Uses 24-hour clock — 0 is midnight, 12 is noon, 23 is 11 PM.

Value Meaning
0Midnight (00:00)
99 AM
175 PM (17:00)
9,179 AM and 5 PM (twice a day)
9-17Every hour from 9 AM to 5 PM
*/6Every 6 hours (at 0, 6, 12, 18)

Field 3: Day of Month (1–31)

Controls which day(s) of the month the job runs. Values are 1–31. Setting this to a non-star value while day-of-week is also non-star triggers an OR — the job runs on days matching either field.

Field 4: Month (1–12 or JAN–DEC)

Controls which months the job runs. Accepts numeric values (1=January through 12=December) or three-letter abbreviations (JAN, FEB, MAR, APR, MAY, JUN, JUL, AUG, SEP, OCT, NOV, DEC). A value of */3 means every quarter (January, April, July, October).

Field 5: Day of Week (0–7 or SUN–SAT)

Controls which weekdays the job runs. Both 0 and 7 represent Sunday — this is a historical quirk. 1=Monday, 2=Tuesday, 3=Wednesday, 4=Thursday, 5=Friday, 6=Saturday. Accepts three-letter names (MON, TUE, WED, THU, FRI, SAT, SUN). A range of 1-5 means Monday through Friday.

Every Special Character — With Real Examples

Asterisk (*) — Any Value

* * * * *       # every minute
0 * * * *       # every hour, on the hour
0 0 * * *       # every day at midnight

Comma (,) — List of Values

0 9,17 * * *    # at 9 AM and 5 PM every day
0 0 1,15 * *    # at midnight on the 1st and 15th of each month
0 9 * * 1,3,5   # at 9 AM on Monday, Wednesday, Friday

Hyphen (-) — Range

0 9-17 * * *    # every hour from 9 AM to 5 PM
0 9 * * 1-5     # at 9 AM on every weekday (Mon-Fri)
0 0 1-7 * 1     # at midnight on the first Monday of every month (approx)

Slash (/) — Step / Interval

*/5 * * * *     # every 5 minutes
*/15 * * * *    # every 15 minutes
0 */2 * * *     # every 2 hours, on the hour
0 */6 * * *     # every 6 hours (00:00, 06:00, 12:00, 18:00)

The slash means "start at X, then every N". So */5 in the minute field means "start at 0, then every 5" — giving 0, 5, 10, 15… You can also combine with ranges: 10-50/10 means "from minute 10 to minute 50, every 10 minutes" — giving 10, 20, 30, 40, 50.

Hash (#) — Nth Weekday of Month (Quartz/Advanced)

0 9 * * 5#1     # 9 AM on the FIRST Friday of each month
0 9 * * 2#3     # 9 AM on the THIRD Tuesday of each month

The # character is supported in Quartz Scheduler (Java) and some enterprise cron implementations, but not in standard Linux crontab. Check your target environment before using it.

L — Last (Quartz/Advanced)

0 23 L * *      # 11 PM on the last day of every month
0 9 * * 5L      # 9 AM on the last Friday of every month

W — Nearest Weekday (Quartz/Advanced)

0 9 15W * *     # 9 AM on the weekday nearest to the 15th of the month

If the 15th is a Saturday, it runs on the 14th (Friday). If the 15th is a Sunday, it runs on the 16th (Monday). Useful for month-end payroll runs or billing cycles that must land on a business day.

30+ Ready-to-Use Cron Expressions

Expression Schedule
* * * * *Every minute
*/5 * * * *Every 5 minutes
*/10 * * * *Every 10 minutes
*/15 * * * *Every 15 minutes
0 * * * *Every hour on the hour
0 */2 * * *Every 2 hours
0 */6 * * *Every 6 hours (4x per day)
0 0 * * *Every day at midnight
0 6 * * *Every day at 6 AM
0 9 * * *Every day at 9 AM
0 12 * * *Every day at noon
0 18 * * *Every day at 6 PM
0 23 * * *Every day at 11 PM
0 9,17 * * *Every day at 9 AM and 5 PM
0 9 * * 1-59 AM every weekday (Mon–Fri)
0 9 * * 19 AM every Monday
0 9 * * 59 AM every Friday
0 0 * * 0Midnight every Sunday
0 0 1 * *Midnight on the 1st of every month
0 0 15 * *Midnight on the 15th of every month
0 0 1,15 * *Midnight on 1st and 15th of each month
0 0 L * *Midnight on last day of each month
0 0 1 */3 *Midnight on 1st of every quarter (Jan, Apr, Jul, Oct)
0 0 1 1 *Midnight on January 1st (New Year)
0 0 * * 1Midnight every Monday (weekly reset)
30 8 * * 1-58:30 AM every weekday (standup time)
0 2 * * *2 AM daily (nightly backup window)
0 3 * * 03 AM every Sunday (weekly maintenance)
0 9-17 * * 1-5Every hour 9 AM–5 PM on weekdays
*/30 9-17 * * 1-5Every 30 min during business hours

Platform Differences — Linux, Kubernetes, AWS, GitHub Actions

Cron syntax is not perfectly standardised. Different platforms support different features and have different edge cases. This is the source of most "my cron expression works on Linux but fails on AWS" confusion.

Linux crontab (Standard)

The original. Five fields. Supports *, ,, -, / in all fields. Supports @daily, @weekly, @monthly, @yearly, @reboot shortcuts. Does NOT support L, W, or #. Runs in the system timezone — check timedatectl to see what timezone your server is in.

Kubernetes CronJob

Uses standard 5-field cron syntax. Defaults to UTC timezone. From Kubernetes 1.25+, you can specify a timezone with the spec.timeZone field (e.g., timeZone: "Asia/Kolkata"). Important caveat: Kubernetes CronJobs have a startingDeadlineSeconds field — if the cluster is unavailable when a job is supposed to start, it will miss the schedule if the missed window exceeds this deadline.

AWS EventBridge (CloudWatch Events)

Uses a 6-field format with year appended: minute hour day-of-month month day-of-week year. Critical difference: you cannot specify both day-of-month and day-of-week as non-star values. One must always be ?. For example: cron(0 12 * * ? *) for daily at noon UTC, or cron(0 12 ? * MON-FRI *) for weekdays at noon. Always UTC — no timezone configuration available for cron expressions (use rate expressions if you need relative timing).

GitHub Actions

Uses standard 5-field cron syntax under the schedule trigger. Always runs in UTC. Minimum interval is every 5 minutes — GitHub will not queue a workflow more frequently. Note: scheduled workflows on the default branch do not run on forks, and GitHub may delay or skip scheduled runs on repositories with low activity. Always UTC — plan accordingly for IST workflows (UTC + 5:30).

Platform Fields Timezone L/W/# Support
Linux crontab5System TZNo
Kubernetes CronJob5UTC (configurable 1.25+)No
AWS EventBridge6 (+ year)UTC onlyPartial (L, W)
GitHub Actions5UTC onlyNo
Quartz Scheduler (Java)6 (+ seconds)ConfigurableYes (L, W, #)

The Timezone Trap — Why Your Cron Runs at the Wrong Time

This is the most common cron mistake in teams working across time zones. The cron expression itself has no timezone information — it is always interpreted in the timezone of the system or platform running it. On most cloud servers and CI platforms, that timezone is UTC.

India Standard Time (IST) is UTC+5:30. If you want a cron job to run at 9:00 AM IST, you need to subtract 5 hours 30 minutes to get the UTC equivalent: 3:30 AM UTC. The cron expression on a UTC server is: 30 3 * * *

Common IST-to-UTC conversions:

IST Time UTC Equivalent Cron Expression (UTC)
6:00 AM IST12:30 AM UTC30 0 * * *
9:00 AM IST3:30 AM UTC30 3 * * *
12:00 PM IST6:30 AM UTC30 6 * * *
6:00 PM IST12:30 PM UTC30 12 * * *
11:30 PM IST6:00 PM UTC0 18 * * *
Midnight IST6:30 PM UTC (prev day)30 18 * * *

Note that IST midnight (00:00 IST) falls on the previous day in UTC (18:30 UTC), which can cause day-of-week calculations to shift. A cron job meant to run at midnight Sunday IST actually fires on Saturday UTC — if your day-of-week field is set to Sunday, it will miss.

Common Cron Mistakes and How to Fix Them

  • Assuming the server timezone is local time: Cloud servers default to UTC. Always check date on the server to confirm timezone before deploying a time-sensitive cron job.
  • Using both day-of-month and day-of-week as non-star: In Linux cron, this triggers an OR — the job runs on either condition. If you want "first Monday of the month," you cannot express that precisely with standard cron syntax. Use the # character (Quartz only) or add a conditional check inside the script itself.
  • Step values that do not align to hour boundaries: */7 in the minute field gives you minutes 0, 7, 14, 21, 28, 35, 42, 49, 56 — then the sequence resets at the top of the next hour back to 0. This means the gap between 56 and the next 0 is 4 minutes, not 7. If you need exactly every N minutes without drift, use a proper interval scheduler rather than cron.
  • Forgetting 0-indexed day-of-week: Sunday is 0 (or 7). Setting day-of-week to 7 for Sunday works in most implementations but not all. Use 0 for safety, or use the name SUN.
  • Relying on cron for sub-minute tasks: Cron minimum resolution is 1 minute. Use systemd timers, Celery beat, or application-level scheduling for sub-minute intervals.
  • Not checking for missed executions: If the server is down when a cron job was scheduled to run, standard cron misses it entirely — there is no catch-up mechanism. For critical jobs, add monitoring (Cronitor, Healthchecks.io) that alerts you when an expected execution does not happen.

How to Use the Cron Expression Generator

  1. Choose your schedule type: Select from presets (every N minutes, daily, weekly, monthly) or go to the manual field editor for full control.
  2. Fill in each field: The generator validates each field in real time and highlights errors — invalid ranges, out-of-bounds values, and syntax errors are flagged before you copy the expression.
  3. Check the next run times: The tool immediately shows the next 10 scheduled executions in plain English (e.g., "Monday, March 17 2026 at 9:00 AM"). This is the fastest way to confirm your expression is correct without having to mentally parse it.
  4. Select your platform: Choose Linux cron, Kubernetes, GitHub Actions, or AWS EventBridge to get the correct format for your target — including the 6-field format for AWS and the ? wildcard requirements.
  5. Copy the expression: One click copies the validated cron string, ready to paste into your crontab, CI config, or cloud scheduler.

Final Thoughts

Cron expressions look cryptic because they are designed for density — five fields that fit in a terminal line and express an enormous range of schedules. Once you understand that each field is just a set constraint on a time component, and that the special characters are consistent shorthand for common patterns (every N, list, range), writing and reading cron becomes fast. The expression 30 3 * * 1-5 takes about two seconds to read as "3:30 AM every weekday" once the syntax is internalised.

The part that always trips people up is the timezone mismatch — a cron expression deployed to a UTC server thinking "9 AM" is local time. Use the generator's next-run preview to catch this before it causes a job to fire at 3:30 AM when your on-call team was not expecting it.

Open the free Cron Expression Generator, build your schedule visually, verify the next 10 run times, and copy a validated expression — no guessing, no manual parsing, no production surprises.

Frequently Asked Questions

What is a cron expression and how does it work?

A cron expression is a string of 5 (or 6) space-separated fields that define a recurring schedule for a task. The fields represent: minute, hour, day-of-month, month, and day-of-week. For example, '0 9 * * 1-5' means 'at 9:00 AM every weekday'. The cron daemon reads this expression and runs the associated command whenever the current time matches all five fields.

What does * mean in a cron expression?

The asterisk (*) in a cron field means 'every valid value for this field'. In the minute field, * means every minute (0–59). In the hour field, * means every hour (0–23). In the month field, * means every month. A fully-starred expression '* * * * *' runs the job every minute of every hour of every day.

How do I write a cron expression to run every 5 minutes?

Use the step value syntax with a slash: '*/5 * * * *'. The */5 in the minute field means 'every 5th minute' — it triggers at 0, 5, 10, 15, 20, 25, 30, 35, 40, 45, 50, and 55 minutes past each hour. The remaining four stars mean every hour, every day, every month, every day of week.

How do I schedule a cron job to run every day at midnight?

Use: '0 0 * * *' — minute 0, hour 0 (midnight), any day of month, any month, any day of week. An alternative that is slightly more readable: '@daily' is a shorthand equivalent to '0 0 * * *' supported by most cron implementations.

What is the difference between cron day-of-month and day-of-week fields?

Both can restrict which days a job runs, but they interact in an OR relationship when both are set to non-star values. For example '0 9 1 * 1' runs at 9 AM on the 1st of every month AND on every Monday — not just on Mondays that fall on the 1st. To run on a specific day of month only, set day-of-week to *. To run on a specific weekday only, set day-of-month to *.

How do I run a cron job on weekdays only (Monday to Friday)?

Use the range syntax in the day-of-week field: '0 9 * * 1-5'. The '1-5' means Monday (1) through Friday (5). Sunday is 0 (or 7 in some implementations). So '0 9 * * 1-5' means 9:00 AM every Monday, Tuesday, Wednesday, Thursday, and Friday.

What does the L character mean in a cron expression?

L stands for 'last'. In the day-of-month field, 'L' means the last day of the month (28, 29, 30, or 31 depending on the month). '0 23 L * *' runs at 11 PM on the last day of every month. In the day-of-week field, '5L' means the last Friday of the month. Note: L is supported in Quartz scheduler and many enterprise cron implementations but not in standard Linux crontab.

How do I write a cron expression for AWS EventBridge or CloudWatch Events?

AWS EventBridge uses a 6-field cron syntax: minute, hour, day-of-month, month, day-of-week, year. Unlike Linux cron, you cannot use * in both day-of-month and day-of-week simultaneously — one must be '?'. For example: 'cron(0 12 * * ? *)' runs daily at noon UTC. The ? means 'no specific value' for that field.

What timezone does cron use?

Standard Linux cron uses the system timezone of the server running crontab, which is often UTC. Kubernetes CronJobs also default to UTC. AWS EventBridge uses UTC exclusively. GitHub Actions cron schedules run in UTC. Always check the timezone of the system running your cron job — a job set to '0 9 * * *' thinking it targets 9 AM IST will actually run at 3:30 AM IST if the server is in UTC.

What is the difference between @daily, @weekly, @monthly, and @yearly shortcuts?

@daily = '0 0 * * *' (midnight every day). @weekly = '0 0 * * 0' (midnight every Sunday). @monthly = '0 0 1 * *' (midnight on the 1st of each month). @yearly or @annually = '0 0 1 1 *' (midnight on January 1st). @reboot runs once at system startup. These shortcuts are supported in most Linux cron implementations but not in all enterprise or cloud scheduler variants.

How do I test a cron expression without waiting for it to run?

Use an online cron expression tester — the Cron Expression Generator shows the next 10 scheduled run times for any expression instantly. This lets you verify the schedule is correct before deploying. For production validation, tools like 'cronitor.io' or the 'cronsim' JavaScript library can generate future run timestamps programmatically.

Can I run a cron job every 30 seconds?

Standard cron has a minimum resolution of 1 minute — you cannot schedule sub-minute intervals with a single cron expression. To run every 30 seconds, a common workaround is to add two cron entries: '* * * * * /path/to/script' and '* * * * * sleep 30 && /path/to/script'. For true sub-minute scheduling, use a process manager like systemd timers (which support seconds resolution) or an application-level scheduler.

Sponsored

Sponsored banner