Quartz.NETQuartz.NET
Home
Features
Discussions
NuGet
GitHub
Home
Features
Discussions
NuGet
GitHub
  • Getting Started

    • Quartz 3 Quick Start
    • Tutorial
      • Using Quartz
      • Library Overview
      • Jobs And Triggers
      • More About Jobs
      • More About Triggers
      • Execution Groups
      • Node Affinity (Preferred Node)
      • Simple Triggers
      • Cron Triggers
      • RecurrenceTrigger
      • Trigger and Job Listeners
      • Scheduler Listeners
      • Job Stores
      • Tuning the Scheduler
      • Configuration, Resource Usage and SchedulerFactory
      • Advanced (Enterprise) Features
    • Configuration Reference
    • JSON Configuration
    • Multi-Tenancy
    • Frequently Asked Questions
    • Best Practices
    • Tenancy Patterns
    • Troubleshooting
    • API Documentation
    • Database Schema
    • Database Schema Changes
    • Migration Guide
    • Miscellaneous Features
  • How To's

    • One-Off Job
    • Multiple Triggers
    • Job Template
    • Using the CronTrigger
    • Rescheduling Jobs
  • Packages

    • Quartz Core Additions

      • Dashboard
      • Jobs
      • Serialization (System.Text.Json)
      • Serialization (Newtonsoft Json.NET)
      • Plugins
    • Integrations

      • ASP.NET Core Integration
      • Hosted Services Integration
      • Microsoft DI Integration
      • Multiple Schedulers with Microsoft DI
      • OpenTelemetry Integration
      • OpenTracing Integration
      • Redis Lock Handler
      • TimeZoneConverter Integration
    • 3rd Party Plugins for Quartz
  • Unreleased Releases

    • Quartz 4.x
      • Quartz 4 Quick Start
      • Tutorial
        • Using Quartz
        • Jobs And Triggers
        • More About Jobs & JobDetails
        • Job Data
        • More About Triggers
        • Querying Jobs and Triggers
        • Simple Triggers
        • Cron Triggers
        • RecurrenceTrigger
        • Time and TimeProvider
        • Trigger and Job Listeners
        • Scheduler Listeners
        • Job Stores
        • Configuration, Resource Usage and Building a Scheduler
        • Building a Scheduler Without a Host
        • Clustering
        • Execution Groups
        • Node Affinity (Preferred Node)
        • Testing
      • Configuration Reference
      • JSON Configuration
      • Cron Expression Reference
      • Multi-Tenancy
      • Frequently Asked Questions
      • Best Practices
      • Tenancy Patterns
      • Database Schema
      • Database Schema Changes
      • Migration Guide
      • Troubleshooting
      • API Documentation
      • How To's
        • One-Off Job
        • Rescheduling Jobs
        • Multiple Triggers
        • Job Template
        • A Job Store of Your Own
        • A Driver Delegate for a New Database
        • Persisting a Custom Trigger Type
        • A Lock Handler of Your Own
      • Packages

        • Quartz Core Additions

          • Jobs
          • Serialization (System.Text.Json)
          • JSON Serialization
          • Plugins
        • Integrations

          • ASP.NET Core Integration
          • HTTP API
          • HTTP Client
          • Dashboard
          • Hosted Services Integration
          • Microsoft DI Integration
          • Multiple Schedulers with Microsoft DI
          • Observability
          • Redis Lock Handler
          • TimeZoneConverter Integration
        • 3rd Party Plugins for Quartz
  • Old Releases

    • Quartz 2.x
      • Quartz 2 Quick Start
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
        • CronTrigger Tutorial
      • Configuration Reference
      • Migration Guide
      • API Documentation
    • Quartz 1.x
      • Tutorial
        • Lesson 1: Using Quartz
        • Lesson 2: Jobs And Triggers
        • Lesson 3: More About Jobs & JobDetails
        • Lesson 4: More About Triggers
        • Lesson 5: SimpleTrigger
        • Lesson 6: CronTrigger
        • Lesson 7: TriggerListeners and JobListeners
        • Lesson 8: SchedulerListeners
        • Lesson 9: JobStores
        • Lesson 10: Configuration, Resource Usage and SchedulerFactory
        • Lesson 11: Advanced (Enterprise) Features
        • Lesson 12: Miscellaneous Features of Quartz
      • API Documentation
  • License

Cron Triggers

CronTriggers are often more useful than SimpleTrigger, if you need a job-firing schedule that recurs based on calendar-like notions, rather than on the exactly specified intervals of SimpleTrigger.

With CronTrigger, you can specify firing-schedules such as "every Friday at noon", or "every weekday and 9:30 am", or even "every 5 minutes between 9:00 am and 10:00 am on every Monday, Wednesday and Friday".

Even so, like SimpleTrigger, CronTrigger has a startTime which specifies when the schedule is in force, and an (optional) endTime that specifies when the schedule should be discontinued.

Cron Expressions

A cron expression is a string of 6 or 7 whitespace-separated fields - seconds, minutes, hours, day-of-month, month, day-of-week and an optional year - where each field takes a value, a list, a range, an increment, or one of the special characters allowed for that field.

0 0 12 ? * WED is a complete expression, and it means "every Wednesday at 12:00 pm".

The full field table, every special character (*, ?, -, ,, /, L, W, # and the H hash token used to spread load across triggers), and a table of worked examples are in the Cron Expression Reference.

Example Cron Expressions

Here are a few more examples of expressions and their meanings - you can find even more in the API documentation for CronTrigger

CronTrigger Example 1 - an expression to create a trigger that simply fires every 5 minutes

    "0 0/5 * * * ?"

CronTrigger Example 2 - an expression to create a trigger that fires every 5 minutes, at 10 seconds after the minute (i.e. 10:00:10 am, 10:05:10 am, etc.).

    "10 0/5 * * * ?"

CronTrigger Example 3 - an expression to create a trigger that fires at 10:30, 11:30, 12:30, and 13:30, on every Wednesday and Friday.

    "0 30 10-13 ? * WED,FRI"

CronTrigger Example 4 - an expression to create a trigger that fires every half hour between the hours of 8 am and 10 am on the 5th and 20th of every month. Note that the trigger will NOT fire at 10:00 am, just at 8:00, 8:30, 9:00 and 9:30

    "0 0/30 8-9 5,20 * ?"

Note that some scheduling requirements are too complicated to express with a single trigger - such as "every 5 minutes between 9:00 am and 10:00 am, and every 20 minutes between 1:00 pm and 10:00 pm". The solution in this scenario is to simply create two triggers, and register both of them to run the same job.

Building CronTriggers

CronTrigger instances are built using TriggerBuilder (for the trigger's main properties) and WithCronSchedule extension method (for the CronTrigger-specific properties).

CronScheduleBuilder.Create(cronExpression) builds the schedule on its own when you want to hold it in a variable or share it between triggers; WithCronSchedule is the same thing inline.

To compose the cron expression string itself programmatically, see Building cron expressions programmatically.

Build a trigger that will fire every other minute, between 8am and 5pm, every day:

ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule("0 0/2 8-17 * * ?")
    .ForJob("myJob", "group1")
    .Build();

Build a trigger that will fire daily at 10:42 am:

ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule("0 42 10 ? * *")
    .ForJob(myJobKey)
    .Build();

or -

ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule("0 42 10 * * ?")
    .ForJob("myJob", "group1")
    .Build();

Build a trigger that will fire on Wednesdays at 10:42 am, in a TimeZone other than the system's default:

ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule("0 42 10 ? * WED", x => x
        .InTimeZone(TimeZones.FindById("Central America Standard Time")))
    .ForJob(myJobKey)
    .Build();

or, with the schedule built first so that several triggers can share it -

CronScheduleBuilder schedule = CronScheduleBuilder
    .Create("0 42 10 ? * WED")
    .InTimeZone(TimeZones.FindById("Central America Standard Time"));

ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule(schedule)
    .ForJob(myJobKey)
    .Build();

TimeZones.FindById is TimeZoneInfo.FindSystemTimeZoneById plus whatever resolvers are registered — which is what makes a Windows id resolve on Linux once the TimeZoneConverter plugin is added.

Build a trigger that fires once per day at a hash-derived time between midnight and 7:59 AM, spreading load across triggers:

ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("nightly-cleanup", "maintenance")
    .WithCronSchedule("0 H H(0-7) * * ?")
    .ForJob("cleanupJob", "maintenance")
    .Build();

CronTrigger Misfire Instructions

The following instructions can be used to inform Quartz what it should do when a misfire occurs for CronTrigger. (Misfire situations were introduced in the More About Triggers section of this tutorial). These instructions are defined in as the CronTriggerMisfireInstruction enum (and API documentation has description for their behavior). The instructions include:

  • CronTriggerMisfireInstruction.IgnoreMisfires
  • CronTriggerMisfireInstruction.DoNothing
  • CronTriggerMisfireInstruction.FireAndProceed

All triggers have the SmartPolicy instruction available for use, and this instruction is also the default for all trigger types. The 'smart policy' instruction is interpreted by CronTrigger as FireAndProceed: one firing happens as soon as the scheduler is back, and the schedule then continues from the next time it comes round. DoNothing skips the missed firings entirely and waits for the next scheduled time; IgnoreMisfires fires every missed firing, as fast as the scheduler can, until the schedule has caught up. CronTriggerImpl.UpdateAfterMisfire is where this happens.

When building CronTriggers, you specify the misfire instruction as part of the cron schedule (via WithCronSchedule extension method):

ITrigger trigger = TriggerBuilder.Create()
    .WithIdentity("trigger3", "group1")
    .WithCronSchedule("0 0/2 8-17 * * ?", x => x
        .WithMisfireInstruction(CronTriggerMisfireInstruction.FireAndProceed))
    .ForJob("myJob", "group1")
    .Build();
Help us by improving this page!
Last Updated: 8/23/26, 6:42 AM
Contributors: Marko Lahma
Prev
Simple Triggers
Next
RecurrenceTrigger