Cron Expression Parser & Next-Run Visualizer
What is a cron expression?
A cron expression is a compact string that describes when a recurring task should run. It was invented for the Unix cron daemon in the 1970s and has become the lingua franca of scheduled jobs.
Each field maps to a time component. Classic Unix cron has 5 fields; modern Java frameworks (Spring, Quartz) add a seconds field at the start.
Field syntax
| Position | Field | Range | Special |
|---|---|---|---|
| 1 | Second (Spring/Quartz only) | 0β59 | |
| 2 (or 1) | Minute | 0β59 | |
| 3 (or 2) | Hour | 0β23 | |
| 4 (or 3) | Day of month | 1β31 | L (last), W (weekday) |
| 5 (or 4) | Month | 1β12 or JANβDEC | |
| 6 (or 5) | Day of week | 0β6 or SUNβSAT | L, # |
Within each field
*β any value5β a specific value5,10,15β a list5-10β a range*/15β step (every 15 starting at 0)5-20/2β range with stepMON-FRIβ named values in day-of-weekJAN,FEBβ named values in month
Common patterns, decoded
| Expression | Meaning |
|---|---|
* * * * * | Every minute |
*/5 * * * * | Every 5 minutes |
0 * * * * | Every hour at minute 0 |
0 0 * * * | Every day at midnight |
0 9 * * MON-FRI | Every weekday at 09:00 |
30 14 * * SUN | Every Sunday at 14:30 |
0 0 1 * * | Midnight on the 1st of every month |
0 0 1 1 * | Midnight on January 1st (once a year) |
0 12 15 * * | 12:00 on the 15th of every month |
0 */6 * * * | Every 6 hours (00:00, 06:00, 12:00, 18:00) |
Scheduling with Spring @Scheduled
Spring uses a 6-field cron format (with seconds):
@Component
public class ReportJob {
@Scheduled(cron = "0 0 9 * * MON-FRI", zone = "Europe/Paris")
public void runDailyReport() {
// Runs every weekday at 09:00:00 Paris time
}
}
Enable scheduling on your application:
@SpringBootApplication
@EnableScheduling
public class App { public static void main(String[] a) { SpringApplication.run(App.class, a); } }
Best practice: always set zone explicitly. Without it, Spring uses the JVM default, which can drift between environments.
Scheduling with Quartz
Quartz is more powerful than @Scheduled: persistence, clustering, misfire handling.
import org.quartz.*;
JobDetail job = JobBuilder.newJob(ReportJob.class)
.withIdentity("report", "group1")
.build();
Trigger trigger = TriggerBuilder.newTrigger()
.withIdentity("reportTrigger", "group1")
.withSchedule(CronScheduleBuilder
.cronSchedule("0 0 9 ? * MON-FRI")
.inTimeZone(TimeZone.getTimeZone("Europe/Paris")))
.build();
Scheduler scheduler = StdSchedulerFactory.getDefaultScheduler();
scheduler.start();
scheduler.scheduleJob(job, trigger);
Quartz uses ? for "no specific value" in day-of-month when day-of-week is set (and vice versa).
Scheduling without a framework
For simple periodic tasks without cron-level flexibility, ScheduledExecutorService is enough:
import java.util.concurrent.*;
ScheduledExecutorService sch = Executors.newSingleThreadScheduledExecutor();
// Every 5 minutes, starting now
sch.scheduleAtFixedRate(() -> runReport(), 0, 5, TimeUnit.MINUTES);
// Fixed delay between the end of one run and the start of the next
sch.scheduleWithFixedDelay(() -> runReport(), 0, 5, TimeUnit.MINUTES);
Use scheduleAtFixedRate for regular cadence, scheduleWithFixedDelay if a run's duration must not overlap the next.
cron-utils β advanced parsing
For programmatic cron parsing (validation, human descriptions, next-execution calculation) in Java, the cron-utils library is excellent:
<dependency>
<groupId>com.cronutils</groupId>
<artifactId>cron-utils</artifactId>
<version>9.2.1</version>
</dependency>
import com.cronutils.model.CronType;
import com.cronutils.model.definition.*;
import com.cronutils.parser.CronParser;
CronParser parser = new CronParser(CronDefinitionBuilder.instanceDefinitionFor(CronType.SPRING));
Cron cron = parser.parse("0 0 9 * * MON-FRI");
ExecutionTime et = ExecutionTime.forCron(cron);
ZonedDateTime next = et.nextExecution(ZonedDateTime.now()).orElseThrow();
Common mistakes
- Confusing Unix cron and Spring/Quartz cron. Spring expects 6 fields, not 5.
0 9 * * MON-FRIin Spring means "at minute 9 on every hour on day-of-month MON to FRI" β not what you want. - Forgetting DST. "Every day at 02:30" skips or repeats on DST transition days. Set
zone = "UTC"if the exact moment matters more than the wall-clock time. - Conflicting day-of-month and day-of-week. In Unix cron, specifying both broadens the match (OR). In Quartz, you must mark one as
?. - Using
0in the Sunday slot. Both0and7mean Sunday in most implementations β be explicit (SUN). - Cron for sub-minute schedules. Unix cron can't run more often than once per minute. Use Spring/Quartz with seconds, or a
ScheduledExecutorService. - Assuming cron expressions validate in the IDE. Most IDEs don't syntax-check them. Always test with a tool like this one, or cron-utils.
Related tools and guides
- Epoch Timestamp β convert the next-execution timestamps
- DateTimeFormatter Playground β format output dates in your log
- JWT Decoder β tokens carrying their own expiration
- Java Online Compiler β try the Spring @Scheduled snippet