Spring cron expression parser

Paste the string from @Scheduled(cron = "...") to see what it means and exactly when it will fire next. Spring uses six fields starting at seconds, so a five-field expression copied from a Unix crontab will not start.

Try one

The six fields

PositionFieldRangeExtras
1Second0-59* , - /
2Minute0-59* , - /
3Hour0-23* , - /
4Day of month1-31? L L-n nW LW
5Month1-12 or JAN-DEC* , - /
6Day of week0-7 or SUN-SAT? dL d#n

Day-of-week counts Sunday as both 0 and 7. Names are case-insensitive.

The mistake that costs an hour: Unix cron has five fields and starts at minutes. Spring has six and starts at seconds. Pasting 0 9 * * * into@Scheduled does not run at 9am — the application fails to start. Prefix a0 to get 0 0 9 * * *.

Two day fields, combined with OR

When day-of-month and day-of-week are both restricted, Spring fires ifeither matches — they are not intersected. So0 0 0 1 * MON runs on the 1st and on every Monday, which is rarely what people mean. Put ? in the field you do not care about:

  • 0 0 0 1 * ? — the 1st of the month, whatever day that is
  • 0 0 0 ? * MON — every Monday

Macros

MacroExpands to
@yearly / @annually0 0 0 1 1 *
@monthly0 0 0 1 * *
@weekly0 0 0 * * 0
@daily / @midnight0 0 0 * * *
@hourly0 0 * * * *

Which time zone does it use

By default @Scheduled uses the JVM's default time zone, which on a server is often UTC even when your laptop is not. Set it explicitly rather than finding out in production:

@Scheduled(cron = "0 0 9 * * MON-FRI", zone = "Asia/Seoul")

The next-run times above are computed in your browser's time zone. If your server runs elsewhere, its schedule shifts accordingly.