getNodi

Cron expression explainer

Read what an expression means, then check when it actually fires. Runs in your browser — no account, nothing sent anywhere.

Try:

In plain English

At 09:00 AM, Monday through Friday

Closest two runs are 1 day apart.

Next runs in UTC

  • Wed 19 Aug, 09:00next
  • Thu 20 Aug, 09:00+1 day
  • Fri 21 Aug, 09:00+1 day
  • Mon 24 Aug, 09:00+3 days
  • Tue 25 Aug, 09:00+1 day
  • Wed 26 Aug, 09:00+1 day

Times are shown in UTC, and account for daylight saving changes in that zone.

The five fields

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

PositionFieldRange
1Minute0–59
2Hour0–23
3Day of month1–31
4Month1–12
5Day of week0–6, Sunday is 0

Within a field, * means every value, */5 means every fifth, 1-5 is a range and 1,15 is a list.

Day of month and day of week are an OR, not an AND

The single most surprising rule in cron. If you set both fields, most implementations run the job when either matches, not both. So 0 0 1 * 1 does not mean “the first of the month, if it is a Monday” — it means “the first of the month, and every Monday”, which is roughly five times as often as intended.

To get the intersection you have to check the date inside your job. There is no cron syntax for it.

Daylight saving, and the run that moves

Cron fires on wall-clock time, and twice a year the wall clock lies. When a zone springs forward from 02:00 to 03:00, the time 02:30 does not exist that day. When it falls back, 02:30 happens twice.

What a scheduler does about that is not standardised, and that is the part worth knowing: some skip the run, some fire it at the next valid moment, some fire it twice on the way back. See it for yourself — set the timezone to America/New_York, the expression to 30 2 * * 0, and the start date to 10 March 2027. That run lands at 03:30 rather than 02:30, because 02:30 was never on the clock.

An hour late is the good outcome. Whether your own scheduler agrees with this preview is a question about your scheduler — which is exactly why a job that must run once a day is better scheduled in UTC, or at least outside 01:00–03:00 local, where the question never comes up.

Running one of these for real

An expression is the easy part. The rest is somewhere to run it from, a retry when your endpoint is briefly down, and a way to find out it stopped firing that is not a customer telling you. That is what getNodi does — it calls your URL on this schedule, records every run, and tells you when one fails. The free plan runs hourly jobs and needs no card.

If your schedule is for Vercel, check it against the Hobby limits first — Vercel rejects several expressions that are valid everywhere else.