Cron expressions

You paste «15 3 * * 1-5» and out comes what it means, in plain words, with the next runs day by day in the time zone you pick. Or the other way round: build the schedule from the menus and take the expression away.

Do not have one? Build it here

The whole calculation happens in your browser: the expression is not sent anywhere.

Which dialect this page reads

Cron is not one single thing, and that is the first thing to know: here we read classic crontab with five fields (minute, hour, day of the month, month, day of the week), plus the six field form with the seconds in front of everything, the one Spring and node-cron write, plus the shorthands @yearly, @monthly, @weekly, @daily, @midnight and @hourly. Sunday can be written 0 or 7, and the English three letter names (MON, FRI, JAN, DEC) work fine.

Whatever does not belong to this dialect gets turned down with the reason spelled out, rather than read halfway: the Quartz symbols (the question mark, the L of the last day, the W of the nearest weekday, the hash of the third Sunday), the seven Quartz fields with the year at the end, and @reboot, which is not a time but an event and so has no next run to work out. The same goes for a range written backwards, like 5-1: everyone reads it their own way, and giving an answer would be worse than declaring it. If today's job is networks rather than schedules, the right page is Subnet calculator.

Day of the month and day of the week go in OR

This is the trap that costs the most hours of all, and it looks like a detail: when both day fields are written, classic crontab does not put them in AND, it puts them in OR. That is, «0 0 13 * 5» does not mean «the thirteenth of the month, if it is a Friday»: it means the thirteenth of the month, and on top of that every Friday. Whoever expected one run a month gets five or six.

The rule only applies when both are restricted. If one of the two is a star, the other one rules on its own, which is the normal case. That is why the list up above is the part that really counts: you read the dates one by one and you notice straight away if they come thicker than you had in mind. When both fields are written, the page says so in words, so that nobody finds out by accident.

Why «*/7» does not mean «every seven minutes»

The step does not count the minutes going by: it restarts from zero every hour. With «*/7» the runs land on minutes 0, 7, 14, 21, 28, 35, 42, 49 and 56, and then it is back to minute 0 of the next hour: between 00:56 and 01:00 four minutes go by, not seven. On a machine doing heavy work, those two close starts are exactly where things pile up.

The count works out when the step divides sixty, that is 2, 3, 4, 5, 6, 10, 12, 15, 20 and 30: only in those cases is «every N minutes» a true description. On the hours the same reasoning applies with twenty-four, so «*/13» is not «every thirteen hours» but hours 0 and 13, with eleven empty hours in between. This is why the sentence you read up above lists the real minutes instead of repeating the step: the handy description is the one that makes you get it wrong.

Daylight saving time, and why every date is checked again

The clock change is the point where even real crons disagree with each other, so the rule of this page is written down rather than implied: we work in wall clock time, and if that hour does not exist that night, because the hands jump forward, the run is skipped and you are told; if instead it exists twice, because they go back, it is counted once, the first time. A real cron, on the same night, might catch up the skipped run or fire two.

For the same reason every date produced is read back: from the instant we return to the wall clock time in the chosen zone and check it field by field with a second piece of code, written a second time on purpose. If the check does not add up nothing gets printed, because a wrong date said with confidence is worse than no date at all. And if all you need is to know what time it is right now somewhere else in the world, the short road is World clock.