Every field in a Salesforce cron expression accepts a specific range of values. Knowing the bounds and the named alternatives prevents the most common cron mistakes.
The fields and their values
| Position | Field | Range | Named values | Notes |
|---|---|---|---|---|
| 1 | Seconds | 0–59 | — | Almost always 0 |
| 2 | Minutes | 0–59 | — | |
| 3 | Hours | 0–23 | — | 24-hour clock; 0 = midnight, 13 = 1 PM |
| 4 | Day-of-Month | 1–31 | — | Use ? if specifying day-of-week |
| 5 | Month | 1–12 | JAN, FEB, MAR, … DEC | Names case-insensitive |
| 6 | Day-of-Week | 1–7 | SUN, MON, TUE, WED, THU, FRI, SAT | 1 = Sunday, use ? if specifying day-of-month |
| 7 | Year (optional) | 1970–2099 | — | Omit unless you want a one-shot run |
Field-by-field detail
Seconds (0–59)
Salesforce accepts seconds but effectively rounds firing to the minute. In practice always write 0.
Minutes (0–59)
Exactly what it sounds like. Combine with / for step values:
0 */15 * * * ?— every 15 minutes (0, 15, 30, 45)0 30 * * * ?— every hour at :30
Hours (0–23)
24-hour clock, 0 = midnight, 12 = noon, 23 = 11 PM. The hour-12 confusion is common — 12 is noon, not midnight.
Day-of-Month (1–31)
Calendar day. Salesforce handles month-length correctly — 31 won’t fire in February. Use L for “last day of month” — handles 28/29/30/31 automatically.
Month (1–12 or JAN–DEC)
0 0 0 1 1 ? → Midnight Jan 1
0 0 0 1 JAN ? → same thing, named
0 0 0 1 1,4,7,10 ? → Quarterly: Jan 1, Apr 1, Jul 1, Oct 1
Day-of-Week (1–7 or SUN–SAT)
| Number | Day | Abbreviation |
|---|---|---|
| 1 | Sunday | SUN |
| 2 | Monday | MON |
| 3 | Tuesday | TUE |
| 4 | Wednesday | WED |
| 5 | Thursday | THU |
| 6 | Friday | FRI |
| 7 | Saturday | SAT |
Use the names — they’re far more readable than numbers and harder to get wrong.
0 0 9 ? * MON-FRI → 9 AM weekdays
0 0 9 ? * SAT,SUN → 9 AM weekends
Year (1970–2099, optional)
Most schedules omit this — they recur indefinitely. Including a year creates a one-shot schedule that runs once on the specified date.
0 0 9 1 1 ? 2027 → 9 AM on January 1, 2027 — fires once
Important value combinations
? in Day-of-Month or Day-of-Week
Exactly one of those two fields must be ?. Reason: the two fields conflict (“Mondays” vs “the 15th”) — Salesforce makes you choose.
Don’t put numeric ranges in named fields
Valid:
0 0 9 ? * MON-FRI0 0 9 ? * 2-6(equivalent)
Not valid:
0 0 9 ? * MON-5(mixed names and numbers in one range)
* is shorthand for “any” — not “0”
0 0 12 * * ?— noon every day (the*in Day-of-Month means “any day”)0 0 12 ? * *— noon every day (the*in Day-of-Week means “any day”)
Both produce the same fires, just with ? in different positions.
Tricky values
| Cron | What it fires |
|---|---|
0 0 0 ? * ? | INVALID — both day fields are ? |
0 0 0 * * * | INVALID — neither day field is ? |
0 0 24 * * ? | INVALID — hours max is 23 (use 0 for midnight) |
0 0 12 31 2 ? | Valid syntax but never fires — Feb 31 doesn’t exist |
0 0 9 ? * 8 | INVALID — Day-of-Week is 1–7 |
Common interview follow-ups
- What’s hour 0? — Midnight (12:00 AM).
- Is day-of-week 0-indexed? — No, 1-indexed where 1 = Sunday.
- Can I express “every 2 days”? —
*/2in Day-of-Month:0 0 0 */2 * ?— every other day. - Can I omit fields? — Year is optional. The other six are required.
Verified against: Apex Developer Guide — Cron Expressions. Last reviewed 2026-05-17.