Cron Expression Generator

Global tools

A cron expression is five fields - minute, hour, day of month, month, day of week - and this page reads one back the way a scheduler would: what each field selects, when the job next runs, and how many times a day or a week that comes to. Paste a whole crontab line and only the schedule is read, because everything after the fifth field is the command rather than the timing.

The five fields of a crontab line - minute hour day-of-month month day-of-week - or six in the dialects below. A `@daily`-style macro works in the first two.

The same expression means different things to different schedulers: `0 12 * * 1` is Monday to Linux and Sunday to Quartz, which counts Sunday as 1. This setting decides which reading the panel reports.

Any IANA zone name. UTC is the default so the run times do not depend on where the page is opened; set it to the zone the server thinks in to see when the job really fires.

Today's date, so the run times are the same in the page's HTML and in this tab. A date counts from 00:00 UTC on that day, which is how a schedule gets checked against a maintenance window; type `now` to count from this moment instead.

Between 1 and 25. A sparse schedule takes longer to answer, because the search walks the calendar a day at a time.

Leave it blank for "cron-schedule.txt".

Results update as you type. Nothing leaves your device.

Read as the 5-field dialect

At 09:00 on Monday-Friday

Wed 2026-11-11 09:00 (UTC+00:00) is the next run, in 9 hours.

Fires
1 per matching day
Per week
5
Next run
in 9 hours
Fields read
5

The next 5 runs in UTC

#  In UTC                Offset     UTC                   From now
-  --------------------  ---------  --------------------  ----------
1  Wed 2026-11-11 09:00  UTC+00:00  2026-11-11T09:00:00Z  in 9 hours
2  Thu 2026-11-12 09:00  UTC+00:00  2026-11-12T09:00:00Z  in 1d 9h
3  Fri 2026-11-13 09:00  UTC+00:00  2026-11-13T09:00:00Z  in 2d 9h
4  Mon 2026-11-16 09:00  UTC+00:00  2026-11-16T09:00:00Z  in 5d 9h
5  Tue 2026-11-17 09:00  UTC+00:00  2026-11-17T09:00:00Z  in 6d 9h

The first column is the wall clock in UTC; the third is the same moment written absolutely in UTC. Counted from 2026-11-11T00:00:00Z.

What each field selects

FieldWrittenMeansNumbers it selects
minute0:0000
hour90909
day of month*every day
month*every month
day of week1-5Mon-FriMon, Tue, Wed, Thu, Fri

The last column is every value the field selects once the ranges, lists and steps are worked out - which is how `*/15` becomes 00, 15, 30 and 45 rather than staying a symbol taken on trust.

What the numbers do not say

  • This dialect counts Sunday as 0 and accepts 7 as a second way of writing it, so 1 is Monday. Quartz counts Sunday as 1, and the same expression would name a different day there.
  • Every time below is counted from 2026-11-11T00:00:00Z - 00:00 UTC on the date in Count from, which is today's date until you change it. The list therefore depends on that date and not on the moment the page was opened, so the copy saved in the page's HTML and the page in your browser list the same runs.
Read in this browser tab from the calendar and nothing else, using the time zone data the browser already ships. Putting the expression into the scheduler that will run it is the only way to be sure that scheduler agrees - this page can tell you what the expression says, not what your server will do with it.

The reason a tool is needed at all is that the same characters mean different things to different schedulers. `0 12 * * 1` is Monday to Linux and Sunday to Quartz, which counts Sunday as 1; the sixth field is *seconds* in one dialect and a *year* in another; `?`, `L`, `W` and `#` are Quartz-only; and a leading `*` in a day field quietly switches off the rule that otherwise joins the two day fields with "or". Every one of those is named on the page instead of being discovered in production.

About this cron expression generator

Overnight, on a Friday, once a quarter at nine in the morning: a cron expression is how a schedule gets written down, and this page reads one back the way a scheduler would - what each of the five fields selects, when the job next runs, and how many times a day or a week that comes to.

The reading is local to the tab: no expression is sent anywhere, which matters when a crontab line names an internal host or a job you would rather not describe. This page is explicit about its dialect - five fields or six, Vixie or Quartz, seconds-first or year-last - and names the traps instead of guessing.

The same characters mean different things to different schedulers: `0 12 * * 1` is Monday to Linux and Sunday to Quartz. The page prints the values a field actually selected and refuses a range that does not wrap. Confirm the dialect before trusting a next-run time in production.

How this cron expression generator works

The five fields, and what may be written in them

The order is minute, hour, day of month, month, day of week, and each field holds a number from its own range: 0-59, 0-23, 1-31, 1-12, 0-7. Anything else in a field is one of four shapes. A range is `1-5` or `MON-FRI`, where names are a courtesy in the month and weekday fields and mean exactly what the numbers do. A list is `1,15,30`. A step is written with a slash and means "every n": `*/15` in the minute field is 0, 15, 30 and 45.

The shape people misread most is a step that follows a number rather than a star. `3/10` does not mean "the 3rd, and then every tenth" - it means "from 3 to the end of the range, every 10", so it selects 3, 13, 23, 33, 43 and 53. The field table on this page prints the values a field actually selected, which is the quickest way to see whether a step did what was intended.

Ranges do not wrap around. `50-10` in the minute field is refused rather than read as an hour spanning midnight, because implementations do not agree on what that would mean - write it as two parts, `50-59,0-10`. Names are case-insensitive, and Sunday may be written `0` or `7` wherever a dialect counts from zero, which is a small mercy and the source of a large confusion.

Five fields or six, and why the sixth one is dangerous

Standard cron has five fields. Everything else is an extension, and the extensions disagree about where the extra field goes. This page reads three shapes. The five-field form is the one in a Linux or macOS crontab and in GitHub Actions schedules. The six-field form taken by `node-cron`, Go’s `robfig/cron` and Spring’s `@Scheduled` puts **seconds first**. Quartz, the Java scheduler, also puts seconds first but adds an optional **year at the end**, so a Quartz expression has six fields or seven.

The trap is that a six-field expression can be valid in more than one of these readings. `0 0 12 * * ?` is Quartz for "noon every day" and is rejected outright by a reading that expects seconds first, because `?` is not a number - a refusal rather than a silent difference, which is the good outcome. The difference is silent for expressions that avoid the Quartz-only symbols: `0 0 12 * * 1` is noon on Sunday to Quartz and noon on Monday to everything that counts Sunday as zero.

Two further shapes are worth knowing even though this page does not read them. AWS EventBridge and CloudWatch put the **minute first and the year last** - `cron(0 12 * * ? *)` - so the same six tokens can mean a completely different schedule there. Jenkins replaces `H` with a number derived from the job name before cron ever sees the expression, and systemd timers use `OnCalendar`, which is not cron syntax at all. Each of those is named in the refusals rather than being read as something it is not.

Day of month and day of week are joined with or

This is the trap that catches people for years. When *both* day fields name particular days, Vixie cron runs the job when **either** matches, not when both do. `0 0 1 * 0` is not "the 1st of the month, when it happens to be a Sunday": it is midnight on the 1st, and also midnight every Sunday. To get "the 1st only when it is a Sunday" the test has to move into the command itself.

A field counts as naming days when it was not written with a leading `*`. That is why `*` and `0-6` are not interchangeable even though both cover every day: `0 0 * * 0-6` fires every day and names a weekday, while `0 0 * * *` names nothing. Quartz solves the same ambiguity by refusing to accept both, requiring a `?` in one of the two fields - and joining what is left with "and" rather than "or".

Quartz also has the day syntax the others lack. `L` in the day-of-month field is the last day of the month, `LW` the last weekday of the month, and `15W` the weekday nearest the 15th - which stays inside the month, so if the 1st is a Saturday then `1W` fires on Monday the 3rd. In the day-of-week field `6#3` is the third Friday and `6L` is the last Friday. Vixie cron has none of these, which is why "the last day of the month" usually becomes a shell test on `date`.

Run times, time zones, and the two hours a year that misbehave

A cron expression names a wall clock, not an instant, so its run times only mean something in a zone. This page reads the expression in the zone you choose and prints both: the wall clock with its offset (`Wed 2026-09-16 09:00`, `UTC+02:00`), and the same moment written absolutely in UTC, which is the form a log search wants. The offset shown is the one in force at that moment rather than today, so a summer job shows the summer offset.

Daylight saving is where a wall clock stops being a total order. When the clocks go forward, the hour that would have been 02:00-03:00 never happens, so a job scheduled at 02:30 has no 02:30 that day. When they go back, that same hour happens twice and so does 02:30. Real implementations disagree about what to do, so this page does not guess: a reading the zone skipped is reported as skipped, and one it repeated is used at its first occurrence, which is when a job on a real machine would run first.

The search walks the calendar rather than a ticking clock, which is why a schedule as rare as 29 February is answered properly: it tests days, not minutes, and reports the runs it found as `2028-02-29`, `2032-02-29` and so on. It looks thirty years ahead, says so when it stops, and never lists a wall-clock time that does not exist in the zone you asked about.

Worked examples

Each example below was run through the calculator on this page when the site was built, so the numbers match what you see when you enter the same inputs.

Every fifteen minutes

Cron expression: */15 * * * * · Who is reading it: 5 fields - Linux, macOS, GitHub Actions · Read the wall clock in: UTC

Read as the 5-field dialect

Every 15 minutes every day

Wed 2026-11-11 00:15 (UTC+00:00) is the next run, in 15 minutes.

Fires: 96 per matching day · Per week: 672 · Next run: in 15 minutes · Fields read: 5

The field table is the part to read here: 00, 15, 30 and 45 are printed as the values the minute field selected, so nothing is left to take on trust. The stat line says 96 runs on a matching day, which is four an hour across twenty-four hours.

Weekdays at nine, in Berlin

Cron expression: 0 9 * * 1-5 · Who is reading it: 5 fields - Linux, macOS, GitHub Actions · Read the wall clock in: Europe/Berlin

Read as the 5-field dialect

At 09:00 on Monday-Friday

Wed 2026-11-11 09:00 (UTC+01:00) is the next run, in 8 hours.

Fires: 1 per matching day · Per week: 5 · Next run: in 8 hours · Fields read: 5

The run times skip Saturday and Sunday and land on the next Monday, and each row carries the offset Berlin has on that date - +02:00 in summer, +01:00 in winter. In UTC the same job fires two hours earlier in summer and one hour earlier in winter, which is the form a log search wants.

The same expression read by Quartz

Cron expression: 0 0 12 * * 1 · Who is reading it: Quartz - Java schedulers, six fields or seven · Read the wall clock in: UTC

Read as the Quartz dialect

At 12:00 on Sunday

Sun 2026-11-15 12:00 (UTC+00:00) is the next run, in 4d 12h.

Fires: 1 per matching day · Per week: 1 · Next run: in 4d 12h · Fields read: 6

Noon on Sunday, not Monday: Quartz counts Sunday as 1. Switch the dialect back to the five-field reading of `0 12 * * 1` and the next run moves from the coming Sunday to the coming Monday - one setting, one day of difference, and nothing in the expression itself to warn you.

The last weekday of the month

Cron expression: 0 0 12 LW * ? · Who is reading it: Quartz - Java schedulers, six fields or seven · Read the wall clock in: UTC

Read as the Quartz dialect

At 12:00 on the last weekday of the month

Mon 2026-11-30 12:00 (UTC+00:00) is the next run, in 19d 12h.

Fires: 1 per matching day · Per week: depends on the month · Next run: in 19d 12h · Fields read: 6

Quartz-only syntax: `LW` is the last weekday of the month, and the question mark says "no specific day of week", which Quartz requires in one of the two day fields. The run times land on the end of each month rather than on a fixed day number, so a month ending on a Saturday gives the Friday before it.

Frequently asked questions

What does a cron expression actually say?

Five fields in this order: minute, hour, day of the month, month, day of the week. `0 9 * * 1-5` is "at minute 0 of hour 9, every day of the month, every month, on Monday through Friday" - nine in the morning on working days. `*` means every value in that field, a range such as `1-5` means those values, a list such as `1,15` means both of them, and a step such as `*/15` means every fifteenth value. Read in order, most expressions say exactly what they look like.

Why did my job run when the day of month did not match?

Because the two day fields are joined with "or" whenever both of them name days. `0 0 1 * 0` fires on the 1st of the month and also on every Sunday; it does not wait for the 1st to fall on a Sunday. That is standard cron behavior rather than a fault in your server, and it is the most common surprise in the format. To fire on the 1st only when it is a Sunday, schedule the 1st and test the weekday inside the command - or use Quartz, which refuses the expression and makes you pick one of the two fields.

Is Sunday 0 or 1, and why does my job run on the wrong day?

It depends on the scheduler, and that is exactly why jobs run on the wrong day. Standard cron counts Sunday as 0 and also accepts 7 for it, so 1 is Monday. Quartz counts Sunday as 1, so 1 is Sunday and 2 is Monday. AWS EventBridge counts 1-7 with Sunday as 1, like Quartz. An expression such as `0 0 12 * * 1` is therefore noon on Sunday in Quartz and noon on Monday everywhere that counts from zero, with nothing inside the expression to warn you. The dialect setting exists for this, and the panel always says which reading it used.

What is the difference between ? and * in Quartz?

Both mean "no value here", and Quartz insists on `?` in one of the two day fields when the other names days: `0 0 12 15 * ?` is the 15th of the month, and `0 0 12 ? * FRI` is every Friday. Writing `*` in both fields is refused, because Quartz joins the two with "and" and that case was never implemented. The distinction matters in the other direction too: `?` in a scheduler that does not have it - a Linux crontab, say - is a syntax error rather than a synonym for `*`.

How do I schedule something for the last day of the month?

In Quartz, write `L`: `0 0 12 L * ?` is noon on the last day of every month and `LW` is the last weekday of the month. Quartz also has `L-3`, three days before the end; this page reads `L` and `LW` but refuses the offset and says so rather than guessing. In standard cron there is no `L`, so the usual workaround is to schedule days 28-31 and let the command check whether tomorrow is the 1st, or to compute the date in the script. Scheduling the 31st does not mean "the last day": it means the 31st, and February is quietly skipped.

What happens to a 02:30 job on the day the clocks go forward?

It depends on the machine, which is the reason it is worth knowing about. When a zone moves from 02:00 to 03:00 there is no 02:30 on that date at all: some cron implementations run the job once, shortly after the change, and some skip it that day, and the details differ between distributions. In autumn the same wall clock happens twice and the job may run once or twice. This page takes no side - it reports the reading as skipped or as doubled and shows the next moment that really happens, so the schedule can be checked against what the server will do.

Which cron does my platform use?

A Linux or macOS crontab, and GitHub Actions, use the five-field Vixie form with Sunday as 0, and Vixie cron has no `L`, `W` or `#`. Quartz (Java) and Jenkins take six fields with seconds first and support `?`, and Quartz adds `L`, `W`, `#` and an optional year. `node-cron`, Go’s `robfig/cron` with seconds enabled, and Spring’s `@Scheduled` take six fields with seconds first and no Quartz symbols. AWS EventBridge takes six fields with the minute first and the year last. Jenkins also replaces `H` with a hash of the job name, and systemd timers use `OnCalendar` rather than cron. Check the scheduler that will run the job: this page reads three of these shapes and names the ones it does not read.

Does this page send my expression anywhere?

No. The expression is read by a fixed rule that runs in your browser tab, the run times are computed from the calendar in the same tab, and there is no endpoint behind the page - the only request it makes is for the page itself. The copy in the page’s HTML is a rendering prepared when the page was published, so a visitor without JavaScript sees a real reading with the moment it was counted from written beside it, rather than an empty result box. Nothing typed here is logged, stored or sent.

Assumptions and sources

  • Field syntax follows the five-field cron that Vixie cron and most Linux systems use; the page also reads the six-field seconds form and Quartz.
  • Forms it does not support (AWS, Jenkins `H`, systemd `OnCalendar`) are named rather than guessed at, and an expression that can never fire is refused.
  • Time zones come from the IANA database built into your browser; nothing is scheduled, sent or uploaded.

Last reviewed 2026-09-16. Runs locally on your device; keep backups; no financial advice applies. Read the full disclaimer.

Where a figure on this page comes from an official agency — HUD, IRS, FICO or a state body — the site keeps a dated snapshot of the source page in its sources library, and a scheduled job re-checks that snapshot, so the number can be traced back to the document it came from.