Spring Cron Expression Generator

Type a Spring @Scheduledcron expression and see, in plain English, when it fires — plus the next ten run times in your time zone. It follows Spring Framework's CronExpression rules (six fields, seconds first, L, W and #), and it converts 5-field Unix and 7-field Quartz expressions so you can paste what you already have.

Runs entirely in your browser · Updated · by Srue, backend engineer

second · minute · hour · day-of-month · month · day-of-week

Meaning

At 09:00, Monday through Friday

Field breakdown
FieldValueMatches
Second00
Minute00
Hour99
Day of month*any
Month*any
Day of weekMON-FRI1, 2, 3, 4, 5

Next 10 runs

Enter a valid expression to see the schedule.

Use it in Spring

@Scheduled(cron = "0 0 9 * * MON-FRI", zone = "UTC")

From application.yml

app:
  jobs:
    report:
      cron: "0 0 9 * * MON-FRI"

# @Scheduled(cron = "${app.jobs.report.cron}", zone = "UTC")

Spring cron vs Unix cron vs Quartz

Most broken schedules come from copying an expression written for a different cron dialect. The three look alike but disagree on field count, day numbering and how the two day fields combine.

Differences between Spring, Unix and Quartz cron
Spring (@Scheduled)Unix crontabQuartz
Fields6 — seconds first5 — no seconds6 or 7 (optional year)
Sunday0 or 7 (or SUN)0 or 71 (or SUN)
Monday112
Day-of-month + day-of-weekboth must matcheither matchesone must be ?
L, W, #yesnoyes
Macros@hourly, @daily, @weekly, @monthly, @yearlysame, plus @rebootno

Field reference

Allowed values per field
PositionFieldValuesSpecial
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* ? , - / nL n#k

L means the last day of the month; L-2 is two days before it. 15W is the weekday nearest the 15th (it never crosses into another month). In the day-of-week field FRIL or 5L is the last Friday, and MON#2 is the second Monday.

Common Spring cron examples

Spring cron examples and what they mean
ExpressionMeaning
*/30 * * * * *Every 30 seconds
0 * * * * *Every minute
0 */5 * * * *Every 5 minutes
0 0 * * * *At minute 0 of every hour
0 0 */2 * * *At minute 0, every 2 hours
0 0 9 * * *At 09:00
0 0 9 * * MON-FRIAt 09:00, Monday through Friday
0 0 9,18 * * *At 09:00 and 18:00
0 0/30 9-18 * * MON-FRIEvery 30 minutes, every hour from 09:00 through 18:00, Monday through Friday
0 0 0 * * SUNAt 00:00, on Sunday
0 0 0 1 * *At 00:00, on day 1 of the month
0 0 23 L * *At 23:00, on the last day of the month
0 0 10 * * MON#1At 10:00, on the 1st Monday of the month
0 0 18 * * FRILAt 18:00, on the last Friday of the month
0 0 9 15W * *At 09:00, on the weekday nearest day 15 of the month
0 0 0 1 JAN *At 00:00, on day 1 of the month, in January

Using the expression with @Scheduled

Enable scheduling once with @EnableScheduling on a configuration class, then put the expression on a no-argument method of a Spring bean. Keep the expression in configuration rather than in code so each environment can change or disable it:

@Component
class ReportJob {

    @Scheduled(cron = "${app.jobs.report.cron}", zone = "Asia/Seoul")
    void sendDailyReport() {
        // ...
    }
}

# application.yml
app:
  jobs:
    report:
      cron: "0 0 9 * * MON-FRI"   # "-" disables the job

Things that bite in production

  • One thread by default.Spring Boot's scheduler pool has a single thread (spring.task.scheduling.pool.size=1), so a slow job delays every other scheduled method. Raise the pool size or hand long work to an executor.
  • Every instance runs the job. With three replicas, a daily email goes out three times. Use a lock such as ShedLock, or run scheduled work in a single dedicated instance.
  • Time zone drift. Containers default to UTC. Set zone explicitly instead of relying on the host.
  • Daylight saving time. In zones with DST, 02:30 does not exist on the night clocks jump forward, so the run moves to 03:30. When clocks fall back, the repeated hour is ambiguous. The run list above resolves both cases the way java.time does — or avoid the problem by scheduling in UTC.
  • Check what is registered. With Spring Boot Actuator, /actuator/scheduledtasks lists every cron task and its expression — useful when a placeholder did not resolve the way you expected.

Frequently asked questions

Why does Spring say “Cron expression must consist of 6 fields”?

You passed a 5-field Unix cron such as "0 9 * * *". Spring's CronExpression starts with a seconds field, so add a leading 0: "0 0 9 * * *". Paste the 5-field version into the tool above and it converts it for you.

Is Sunday 0 or 7 in Spring cron?

Both. Spring accepts 0 and 7 for Sunday, 1 for Monday through 6 for Saturday, and the names SUN–SAT. Quartz is different: there 1 is Sunday and 7 is Saturday, which is the most common bug when moving a job from Quartz to @Scheduled.

Can I use “?” in a Spring cron expression?

Yes. In the day-of-month and day-of-week fields Spring treats "?" exactly like "*". It is optional — unlike Quartz, Spring does not require one of the two fields to be "?".

What happens if I set both day-of-month and day-of-week?

Spring fires only when both match. "0 0 9 13 * FRI" runs on Friday the 13th only. Classic Unix cron does the opposite and fires when either field matches, so the same pattern copied from crontab behaves differently.

Which time zone does @Scheduled use?

The JVM default time zone unless you set the zone attribute, e.g. @Scheduled(cron = "0 0 9 * * *", zone = "Asia/Seoul"). Containers usually run in UTC, so a job written as 09:00 can quietly run at 09:00 UTC.

How do I turn a scheduled job off from configuration?

Set the cron value to "-" (Scheduled.CRON_DISABLED). With @Scheduled(cron = "${app.jobs.report.cron}") you can disable the job in one environment by setting app.jobs.report.cron: "-" there.

Does Spring cron support a year field?

No. Spring cron has exactly six fields. If you need a one-off date in a specific year, check the year inside the method or use a different trigger.