问题
I need to create a Quartz cron expression that fires every 10th day of the month if it is a weekday, otherwise fires to the next day or the day after the next.
- E.g. August 10th 2014 is Sunday, fire Monday 11th
- E.g. September 10th 2014 is Wednesiday, fire Wednesday 10th
- E.g. January 10th 2015 is Saturday, fire Monday 12th
I highlighted the third case: I tried 0 0 0 10W * ?
as expression but it fires Friday Jan 8th 2015. I need it to be fired later.
How do I tell Quartz to? I wanted to make three expressions, e.g. "the 10th if it is a weekday", "11th if it is a monday" and "12th if it is a monday" but I can't combine day-of-month and day-of-week fields (I always get an Invalid cron expression error)
回答1:
I don't think you can do that with a simple cron expression, but you can use the following solution.
First schedule your Job with a classic Cron Trigger
CronScheduleBuilder sh = cronSchedule("0 0 0 10 * ?");
TriggerBuilder<Trigger> tb = newTrigger()
.withSchedule(sh)
.withIdentity("MyTrigger");
And schedule your Trigger. Then create a Quartz TriggerListener that implements your mecanism
public class MyTriggerListener implements TriggerListener {
[...]
@Override
public void vetoJobExecution(Trigger trigger, JobExecutionContext context) {
// You check if it is your Cron Trigger
if ("MyTrigger".equals(trigger.getKey.getName()) {
Calendar cal = Calendar.getInstance();
// If current date is sunday, then another one-time trigger
// is created to delay the job firing
if (Calendar.SUNDAY.equals(cal.get(Calendar.DAY_OF_WEEK))) {
cal.add(Calendar.DATE, 1); // One day later
TriggerBuilder<Trigger> tb = newTrigger()
.startAt(cal.getTime());
.withIdentity("MyTrigger_delayed");
.forJob(context.getJobDetail());
// TODO schedule it in Quartz the way you want
// like : scheduler.scheduleJob(tb.build());
return true; // The current fire is vetoed
}
// If current date is saturday, then another one-time trigger
// is created to delay the job firing
else if (Calendar.SATURDAY.equals(cal.get(Calendar.DAY_OF_WEEK))) {
cal.add(Calendar.DATE, 2); // Two day later
TriggerBuilder<Trigger> tb = newTrigger()
.startAt(cal.getTime());
.withIdentity("MyTrigger_delayed");
.forJob(context.getJobDetail());
// TODO schedule it in Quartz the way you want
// like : scheduler.scheduleJob(tb.build());
return true;// The current fire is vetoed
}
// If it is a weekday, the job fires normally
else {
return false;
}
}
// It is not your Cron Trigger
return false;
}
}
This code implement a mecanism to delayed your job firing to start the job a weekday. You can add this Listener to your Scheduler with
TriggerListener myTriggerListener = new MyTriggerListener("MyTriggerListener");
scheduler.getListenerManager().addTriggerListener(myTriggerListener, allTriggers());
来源:https://stackoverflow.com/questions/25115034/posticipate-quartz-expression-to-the-next-weekday