← All posts

Cron syntax was not designed for humans

Cron is from 1975. It's older than most developers using it. The syntax — five fields separated by spaces, with special characters like `*`, `/`, `,`, `-`, `?`, and `#` — was designed for an environment where every byte mattered. The trade-off shows.

The five-field problem

A cron line is "minute hour day-of-month month day-of-week". Most people remember the order wrong. Did the day come before the hour? Is Sunday 0 or 7? Both, depending on the cron implementation.

Even simple schedules trip people up. "Every weekday at 9am" is `0 9 * * 1-5`. "Every 15 minutes during business hours on weekdays" is `*/15 9-17 * * 1-5`. Reading it back to confirm what you wrote is harder than writing it the first time.

"First Monday of the month" is genuinely hard

The naive `0 10 1-7 * 1` matches "every Monday between the 1st and the 7th of the month at 10am" — which gives you the first Monday, but only if the 1st of the month is a Monday or earlier. It's an OR clause: day of month 1–7 OR day of week Monday. Wrong.

The Quartz extension solves this with `0 10 ? * MON#1` — the `#1` means "first occurrence of Monday in the month". Standard cron doesn't have this. Different schedulers (Linux cron, Quartz, Spring, AWS EventBridge) implement different subsets of the syntax.

There are at least four different "cron" syntaxes in widespread use today. They look identical until you hit the edge cases (last weekday of month, nth weekday, seconds field).

The DST trap

Cron daemons run in local time by default. A job scheduled for 2:30am will fire twice on the fall-back DST day (when 2am happens twice) and zero times on the spring-forward day (when 2am gets skipped).

This is fine for daily backups but disastrous for billing or reporting jobs. The fix is to run cron in UTC and translate user-facing times — but that introduces its own confusion when users edit schedules in their head, in their local time.

Testing without firing

Most schedulers don't have a "what would this fire" preview. You write the cron expression, deploy it, and find out tomorrow if it ran when you expected. By the time you realize the schedule was wrong, you've missed a window.

The fix is a tool that takes your expression, computes the next 14 days of fire times, and shows them on a calendar. You eyeball it before deployment. Saves a week of "wait, why didn't the report run?".

Our cron job editor accepts plain English ("every weekday at 9am", "first Monday of every month at 10:30") and outputs the cron expression, then shows a calendar preview of the next fire times. It's DST-aware, supports IANA time zones for translation, and copies the expression to your clipboard when you're ready to deploy.

Try the tool