2014-09-24 113 views
8

我可以使用Quartz Scheduler库,设置如下?:我可以使用Quartz Scheduler在第30天每隔一个月发射一次,但如果月份没有第30天,最后一天发射?

  • 月,30日开始创建计划2014
  • 执行每30天
  • 每2个月因此
  • 如果月份没有第30天,则应在的最后一天发生操作。

因此,所产生的时间表将是:

  • 2014年12月30日
  • 月,2015年
  • 2015年4月30日
  • ...等

从我所了解到的:

  1. CronTrigger不允许这样做(它可以被设置为仅要在特定的月份,而不是间隔触发),
  2. CalendarIntervalTrigger将跳过没有30天做个月(触发通过下面的代码创建)

    try { 
        SchedulerFactory schedulerFactory = new StdSchedulerFactory(); 
        Scheduler scheduler = schedulerFactory.getScheduler(); 
        scheduler.start(); 
    
        JobDetail jobDetail = JobBuilder.newJob(HelloJob.class) 
          .withIdentity("HelloJob_CalendarIntervaled", "calendarIntervaled") 
          .build(); 
    
        Calendar decemberThirty = Calendar.getInstance(); 
        decemberThirty.set(Calendar.YEAR, 2014); 
        decemberThirty.set(Calendar.MONTH, Calendar.DECEMBER); 
        decemberThirty.set(Calendar.DAY_OF_MONTH, 30); 
    
        CalendarIntervalTrigger calendarIntervalTrigger = newTrigger() 
          .withIdentity("calendarIntervalTrigger", "calendarIntervaled") 
          .withSchedule(CalendarIntervalScheduleBuilder.calendarIntervalSchedule() 
            .withIntervalInMonths(2)) 
          .startAt(decemberThirty.getTime()) 
          .forJob(jobDetail) 
          .build(); 
    
        scheduler.scheduleJob(jobDetail, calendarIntervalTrigger); 
    
        System.out.println(calendarIntervalTrigger.getNextFireTime()); 
    } catch (SchedulerException e) { 
        e.printStackTrace(); 
    } 
    

如果没有,是否有任何替代品(它应该在JBoss EAP 6.2.0工作)?

+3

最迟的实施:每天开启工作,检查工作开始时是否有效。我不知道你的情况会有多么实际(安装成本等),但它可以让你使用日期API,将正确的日期逻辑移动到一个方法,记录和测试它,等等。 – ssube 2014-09-24 14:03:40

回答

5

你可以在Quartz中实现这个功能,但是你必须通过使用CalendarIntervalTrigger来触发一个Job来计算你的'真实'Job应该被调度的时间。

您安排火你安排个月每月第一个触发器:

[...] 
JobDetail jobDetail = newJob(SchedulingCalculationJob.class) 
     .withIdentity("SchedulingCalculation_CalendarIntervaled", "calendarIntervaled") 
     .build(); 

CalendarIntervalTrigger calendarIntervalTrigger = newTrigger() 
     .withIdentity("calendarIntervalCalculationTrigger", "calendarIntervaled") 
     .withSchedule(calendarIntervalSchedule() 
       .withIntervalInMonths(2)) 
     .startAt(decemberFirst.getTime()) 
     .forJob(jobDetail) 
     .build(); 

scheduler.scheduleJob(jobDetail, calendarIntervalTrigger); 

而在SchedulingCalculationJob工作,你算算你的“真实”工作调度天:

public class SchedulingCalculationJob implements Job { 

    public void execute(JobExecutionContext context) 
      throws JobExecutionException { 

     Calendar calendar = calculateJobFiringDate(); 

     // Create and schedule a dedicated trigger 
     Trigger calculateFiring = calculateFiring = newTrigger() 
       .withSchedule(SimpleSchedulerBuilder.simpleScheduler()) 
       .startAt(calendar.getTime()) 
       .forJob(yourRealJobDetail) 
       .build(); 

     scheduler.scheduleJob(yourRealJobDetail, calculateFiring); 
    } 

    public static Calendar calculateJobFiringDate() { 
     Calendar result = Calendar.getInstance(); 

     // Set up the scheduling day 
     if (isThereThirtyDaysInCurrentMonth()) { 
      // the 30th of the current month 
      calendar.set(Calendar.DAY_OF_MONTH, 30); 
     } else { 
      // the last day of the current month 
      calendar.add(Calendar.MONTH, 1); 
      calendar.add(Calendar.DATE, -1); 
     } 

     // Set up time of day 
     calendar.set(Calendar.HOUR, ...); 
     calendar.set(Calendar.MINUTE, ...); 
     calendar.set(Calendar.SECOND, ...); 

     return result; 
    } 

    public static boolean isThereThirtyDaysInCurrentMonth() { 
     Calendar thirtydaysInCurrentMonthCalendar = Calendar.getInstance(); 

     Integer currentMonth = thirtydaysInCurrentMonthCalendar.get(Calendar.MONTH); 
     thirtydaysInCurrentMonthCalendar.add(Calendar.DATE, 29); 

     return (currentMonth == thirtydaysInCurrentMonthCalendar.get(Calendar.MONTH); 
    } 
} 

这是一个有点苏族,但我已经使用它,我工作正常。

+0

好一个! Upvoting,现在我有东西坚持:)。 我想也许有更多的“计划”的方式来做到这一点,而无需额外的计算或一些Quartz方法将具体日期添加到CalendarIntervalTrigger ...我会等待一段时间,如果没有,我会接受你的答案。 – n1k1ch 2014-09-24 14:21:53

+1

我稍微增强了一些代码,您只需要在'execute'方法中检索'真正'的工作细节和调度程序引用,其余部分应该可以工作;) – Kraiss 2014-09-24 14:30:02

+0

我们可以在某处指定结束日期吗?直到它会触发? – Elizabeth 2016-04-07 06:56:29

相关问题