Explain Spring's cron support: the field layout, the zone attribute, and how CronExpression is used. How does Spring's cron differ from classic Unix cron?
answer
- 6 fields: sec min hour dom month dow
- Unix cron = 5 fields (no seconds)
- zone attr for DST
- "-" disables the job
- CronExpression.parse(...).next(...)
basics
~20 s@Scheduled(cron = "...") uses a six-field expression: second, minute, hour, day-of-month, month, day-of-week. Unlike Unix cron it has a leading seconds field. Add zone = "Europe/Paris" to pin the time zone, and use the special value "-" to disable the task.
solid answer
~40 sSpring cron uses six space-separated fields: seconds, minutes, hours, day-of-month, month, day-of-week (Unix cron has five — no seconds). Each field allows numbers, ranges (1-5), lists (MON,WED), steps (0/15), and wildcards * and ?; Spring also supports macros like @daily/@hourly and special tokens L (last), W (weekday), and # (nth weekday). By default it evaluates in the server's local time zone; the zone attribute (cron = "...", zone = "Europe/Paris") pins it, which matters for DST. The literal cron value "-" disables the scheduled method entirely, handy for turning a job off via a property. Under the hood Spring parses the string with org.springframework.scheduling.support.CronExpression (Spring 5.3+), which you can also use standalone via CronExpression.parse(...).next(temporal) to compute the next fire time. cron cannot be combined with fixedRate/fixedDelay or initialDelay.
code
java · 18 lines@Component
public class Reports {
// 02:00:00 every day, pinned to Paris time
@Scheduled(cron = "0 0 2 * * *", zone = "Europe/Paris")
public void nightlyReport() { }
// Every 5 minutes on weekdays, business hours
@Scheduled(cron = "0 */5 9-17 * * MON-FRI")
public void poll() { }
// On/off via property; "-" (the default) disables it
@Scheduled(cron = "${cleanup.cron:-}")
public void cleanup() { }
}
// Standalone next-fire computation:
// CronExpression.parse("0 0 2 * * *").next(LocalDateTime.now());go deeper
Knows it is a cron string with day/time fields.
Knows the six-field layout, the seconds field, zone, and the "-" disable trick.
Handles DST correctly and uses CronExpression for previews/tests.
Designs zone-explicit schedules across regions and property-driven enable/disable, aware of DST double/skip edge cases.
**Field layout (six fields).** Spring's cron string is six whitespace-separated fields, in this order: second (0-59), 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, where 0 and 7 both mean Sunday). The **leading seconds field** is the headline difference from classic **Unix cron**, which has only five fields (minute through day-of-week). Copy-pasting a 5-field Unix expression into Spring shifts every field and misfires — a frequent bug. **Allowed syntax per field.** - `*` — any value. - `?` — 'no specific value', used in day-of-month **or** day-of-week to say 'I'm specifying the other one'. - ranges: `9-17`. - lists: `MON,WED,FRI` or `1,15`. - steps: `0/15` (starting at 0, every 15) or `*/15`. - names: months `JAN-DEC`, days `MON-SUN` (case-insensitive). - **special tokens** (Spring's `CronExpression`): `L` = last (last day of month, or in DoW `5L` = last Friday), `W` = nearest weekday to a day-of-month (`15W`), `#` = nth weekday (`FRI#3` = third Friday), `LW` = last weekday of month. **Macros.** Spring accepts convenience macros: `@yearly`/`@annually`, `@monthly`, `@weekly`, `@daily`/`@midnight`, `@hourly`. These expand to standard expressions. (`@reboot` is not supported.) **Examples.** - `0 0 2 * * *` — every day at 02:00:00. - `0 */5 * * * *` — every 5 minutes (at second 0). - `0 0 9-17 * * MON-FRI` — top of every hour 9–17, weekdays. - `0 0 0 L * *` — midnight on the last day of each month. **Time zone / DST.** By default the expression is evaluated in the JVM's default time zone. Pass `zone`: `@Scheduled(cron = "0 0 2 * * *", zone = "Europe/Paris")`. This matters across daylight-saving transitions: a job at 02:30 local may run twice or be skipped on DST boundaries depending on the zone, so always set `zone` explicitly for wall-clock jobs in multi-region systems. **Disabling a job.** The special string value `"-"` means 'never run' — Spring registers the method but schedules nothing. Combined with a property placeholder this is the idiomatic on/off switch: `@Scheduled(cron = "${report.cron:-}")` runs only if the property is set. **`CronExpression` (the standalone API).** Since Spring 5.3, parsing is done by `org.springframework.scheduling.support.CronExpression` (replacing the older `CronSequenceGenerator`). You can use it directly to compute fire times without any scheduling infrastructure: `CronExpression.parse("0 0 2 * * *").next(LocalDateTime.now())`. `CronExpression.isValid(String)` validates an expression. This is useful for previewing schedules, tests, or building admin tooling. (Note: turning a *dynamically computed* schedule into a live task via a `Trigger`/`SchedulingConfigurer` is a separate, sibling topic.) **Constraints.** `cron` is mutually exclusive with `fixedRate`/`fixedDelay`, and `initialDelay` is not allowed with `cron`. An invalid cron string fails fast at startup. **When to use.** Use cron for **wall-clock** schedules ('02:00 daily', 'first of the month', 'weekdays only') where the human-meaningful time matters. Use fixedRate/fixedDelay for simple 'every N seconds' cadences where wall-clock alignment is irrelevant.
- A teammate pasted a 5-field crontab line into @Scheduled(cron=...) and the job fires at the wrong time. Why?Spring cron has six fields with a leading seconds field. A 5-field Unix expression shifts every field left by one, so minutes become seconds, hours become minutes, etc. Add the seconds field (e.g. prefix '0 ').
- How do you disable a @Scheduled(cron=...) job via configuration without deleting code?Set the cron value to the special string "-", typically through a property placeholder like cron = "${job.cron:-}". Spring keeps the method registered but schedules no executions.
saying these in an interview costs you the question
- Using a 5-field Unix expression and expecting Spring semantics
- Assuming cron always uses the local zone even across regions/DST
- Trying to combine cron with fixedRate or initialDelay
- Thinking * and ? are interchangeable in day-of-month/day-of-week