The Util Kit

Salesforce CRON Expression Builder

Build a CRON expression for Salesforce scheduled Apex, or paste one in to see what it means and when it will next run. Uses Salesforce's own syntax, not standard Unix cron. Everything runs in your browser.

Runs entirely in your browser — nothing you enter is uploaded or stored.

Build

Time of day
::24-hour clock

Parse

Every day at 9:00 AM

Next 5 runs

Scheduled Apex runs in the timezone of the user who scheduled the job — not necessarily this one.

  1. Saturday, August 15, 2026 at 9:00:00 AM
  2. Sunday, August 16, 2026 at 9:00:00 AM
  3. Monday, August 17, 2026 at 9:00:00 AM
  4. Tuesday, August 18, 2026 at 9:00:00 AM
  5. Wednesday, August 19, 2026 at 9:00:00 AM

Apex snippet

System.schedule('My Scheduled Job', '0 0 9 * * ?', new MyClass());

Salesforce CRON is not Unix cron

If you've used a general-purpose cron builder for a Salesforce job, this is why the result may not have behaved as you expected.

The field count is different. Unix cron takes five fields. Salesforce takes six, with an optional seventh:

Seconds Minutes Hours Day_of_month Month Day_of_week [Year]

The leading seconds field is the one people miss. Paste a five-field Unix expression into Salesforce and it either fails or is interpreted with every field shifted.

Day-of-week numbering is different, and this one is dangerous. Salesforce numbers days 1–7 with 1 = Sunday, so Monday is 2. Unix cron uses 0–6 with 0 = Sunday, so Monday is 1.

Copy a number across from a Unix cron tool and your job runs on the wrong day — with no error, because the value is valid in both systems. It just means something different.

Using day names (MON, TUE) rather than numbers sidesteps this entirely, and is worth doing for that reason alone.

Salesforce supports extra special characters that standard cron doesn't: ? for "no specific value", L for last, W for nearest weekday, and # for the nth weekday of a month.

You must use ? in one of the day fields. Day_of_month and day_of_week can't both be specified — one has to be ?. This trips people up because Unix cron happily accepts both.

The special characters

  • * — every value for that field.
  • ? — no specific value. Required in whichever of day_of_month or day_of_week you aren't using.
  • , — a list. MON,WED,FRI in day_of_week.
  • - — a range. MON-FRI, or 1-15 in day_of_month.
  • / — increments. 0/15 in the minutes field means every 15 minutes starting at 0.
  • L — last. In day_of_month it means the last day of the month, which correctly handles months of different lengths and leap years. In day_of_week it means the last occurrence of that weekday in the month.
  • W — the nearest weekday to a given day of the month, for jobs that shouldn't land on a weekend.
  • # — the nth occurrence of a weekday in the month. 6#3 is the third Friday, given that 6 is Friday under Salesforce's numbering.

Timezones, and the mistake everyone makes once

A scheduled Apex job runs in the timezone of the user who scheduled it — not the org's default timezone, and not the timezone of whoever looks at it afterwards.

That has some consequences worth knowing before you schedule anything important:

  • If an admin in one timezone schedules a job, and later a colleague elsewhere assumes it runs in theirs, the job will appear to fire at the "wrong" time. It isn't wrong; it's running in the scheduling user's timezone.
  • If the scheduling user's timezone observes daylight saving, the job's actual UTC run time shifts twice a year. For a nightly job that's usually fine. For a job that has to align with an external system or a batch window, it may not be.
  • If the user who scheduled a job is deactivated, it's worth checking what happens to their scheduled jobs in your org rather than assuming.

A common practice is to schedule production jobs from a dedicated integration user whose timezone is set deliberately — often GMT — so the behaviour is predictable and doesn't depend on which admin happened to run the code.

The next-run times shown above use whichever timezone you select, so you can check what a job would do from a particular user's perspective.

Common expressions

ScheduleExpression
Every day at 2:00 AM0 0 2 * * ?
Every weekday at 9:00 AM0 0 9 ? * MON-FRI
Every 15 minutes0 0/15 * * * ?
Every hour on the hour0 0 * * * ?
First day of every month at midnight0 0 0 1 * ?
Last day of every month at 11:00 PM0 0 23 L * ?
Third Friday of every month at 10:00 AM0 0 10 ? * 6#3
Every Monday at 8:30 AM0 30 8 ? * 2

Note the 2 for Monday in that last one — Sunday being 1 is the detail worth double-checking every time you write one of these by hand.

Scheduling from Apex

Once you have an expression, scheduling looks like this:

System.schedule('My Nightly Job', '0 0 2 * * ?', new MyScheduledClass());

The class needs to implement Schedulable. The tool above generates this line for you with your expression already in place.

A few practical notes. Job names must be unique, so re-running a schedule with the same name will fail unless you abort the existing one first. Orgs have a limit on how many scheduled Apex jobs can exist at once, so check the current limit in Salesforce's documentation if you're scheduling many. And scheduled jobs can also be created through the Setup UI, which is simpler for one-off schedules but gives you less control over the expression than scheduling from Apex does.

Frequently asked questions

Is my data sent to a server?
No. Everything is calculated in your browser. Nothing you enter is uploaded or stored.
Why doesn't my Unix cron expression work in Salesforce?
Most likely the field count — Salesforce needs six or seven fields, with seconds first, while Unix cron uses five. Day-of-week numbering also differs, so a numeric weekday copied across will point at the wrong day.
Which day is 1 in Salesforce CRON?
Sunday. Monday is 2 and Saturday is 7. Unix cron uses 0 for Sunday, which is the source of a lot of off-by-one scheduling bugs. Using day names avoids the problem.
Why do I need a ? in my expression?
Salesforce doesn't allow both day_of_month and day_of_week to be specified, so whichever one you aren't using must be ?.
What timezone does a scheduled job run in?
The timezone of the user who scheduled it — not the org default. Check the scheduling user's personal timezone setting if a job runs at an unexpected hour.
Can I schedule something more often than once an hour?
Yes, using increments such as 0 0/15 * * * ? for every 15 minutes. Be mindful of governor limits and the number of scheduled jobs your org allows.
Does the seconds field actually matter?
It's part of the expression and must be present. In practice most jobs use 0, and Salesforce doesn't guarantee execution at an exact second — scheduled jobs are queued and run when resources allow, so treat the schedule as "no earlier than" rather than exact.
Is it free?
Yes, completely free with no sign-up.