DEV Community

Devanshu Biswas
Devanshu Biswas

Posted on

I Built a Cron Visualizer for Spring @Scheduled (6 Fields, Not 5)

Cron expressions are write-once, debug-forever — and Spring's flavour has a trap most people hit: it uses 6 fields, not 5. The cron you copied from a Linux crontab is silently off by one. So I built a tool that parses the Spring format and shows you the actual fire times.

▶ Live demo: https://dev48v.github.io/cron-visualizer/
Source (single file, zero deps): https://github.com/dev48v/cron-visualizer

Type an expression and get a plain-English description, a field-by-field breakdown, and the next 10 times it fires — the only real way to know a cron does what you meant.

The Spring 6-field format

 ┌───────────── second (0-59)   ← Spring adds this; crontab doesn't have it
 │ ┌─────────── minute (0-59)
 │ │ ┌───────── hour (0-23)
 │ │ │ ┌─────── day-of-month (1-31)
 │ │ │ │ ┌───── month (1-12 or JAN-DEC)
 │ │ │ │ │ ┌─── day-of-week (0-7 or MON-SUN; 0 & 7 = Sunday)
 0 0 9 * * MON-FRI09:00:00, Monday through Friday
Enter fullscreen mode Exit fullscreen mode

@Scheduled(cron = "0 0 9 * * MON-FRI") is not the same as the 5-field 0 9 * * 1-5 you'd put in crontab — the leading 0 is seconds, not minutes. Paste a 5-field expression into Spring and you get a startup error (or worse, the wrong schedule).

The gotchas it surfaces

  • 6 fields, not 5. The seconds field is the #1 source of "why did my job run every minute?"
  • day-of-month vs day-of-week. If you restrict both (e.g. 15 * * 1 = the 15th AND Mondays), Spring fires when either matches — usually not what you want. Put ? on the field you don't care about.
  • 0 and 7 both mean Sunday.
  • */15 starts at zero. 0 */15 * * * * fires at :00, :15, :30, :45 — handy to see laid out.

Computing "next fire" without brute force

Iterating second-by-second to find the next match is hopeless for a sparse cron (a yearly job is ~31M seconds away). The tool uses a field-jumping algorithm: if the month doesn't match, jump to the first of the next allowed month and reset the lower fields; if the day doesn't match, jump a day; and so on. It converges in a handful of steps regardless of how rare the schedule is — the same approach real cron libraries use.

One index.html, no build, works offline. If it saved you a misfired job, a star helps others find it: https://github.com/dev48v/cron-visualizer

Top comments (0)