2012-07-11 61 views
3

guys, 每30天使用Quartz的月度工作

我的用戶按月安排工作(使用石英)。用戶提供的起始日期爲f 或第一份工作要運行,可能是一個月中的任何一天1-31

我的問題是如何使用cron觸發器安排此事,記住並非所有月份都有31,30,29天。 在這種情況下,工作應該在最接近該月的前一天。 因此,可以說4月份只有30天,所以工作必須在4月30日進行。

可以使用單個cron觸發器來完成嗎?或者它應該是觸發器的組合? 我試着用CronExpression玩,看看它是如何處理這種情況下:

CronExpression ce = new CronExpression("0 0 0 30 JAN-DEC ? *"); 
Date nextValidTime = ce.getNextValidTimeAfter(//**27th of February**//); 

我有nextValidTime等於 3月,因此只需cron的「跳過」二月。 任何幫助將不勝感激。提前致謝。

回答

6

'月'字符被允許用於月份和星期幾字段。這個字符>對於「last」是短手,但在兩個字段中的每個字段中具有不同的含義。例如,對於 示例,日期字段中的值「L」意味着「該月的最後一天 」 - 一月的第31天,二月的第28天的非閏年 年。如果單獨在星期幾字段中使用,則僅表示「7」 或「SAT」。但是,如果在星期幾字段中使用另一個值,則其 表示「該月的最後一個xxx日」 - 例如「6L」表示「該月的最後一個星期五爲 」。您還可以指定一個月的最後一天的偏移量,例如「L-3」,這意味着該日曆月的倒數第三天爲 。當使用'L'選項時, 很重要,不會指定列表或值的範圍,因爲您會得到 混淆/意外的結果。

http://quartz-scheduler.org/api/2.0.0/org/quartz/CronExpression.html

new CronExpression("0 0 0 L JAN-DEC ? *"); 

編輯:

我只想做這樣的事情,然後

Calendar tCalendar = Calendar.getInstance(); 
tCalendar.set(2009, Calendar.FEBRUARY/*int*/, 1); // for example Feb, 2009 -- day doesn't matter here 
if(userSelectedDay > tCalendar.getActualMaximum(Calendar.DAY_OF_MONTH)){ 
    //Fix user day 
    //fixedDay = tCalendar.getActualMaximum(Calendar.DAY_OF_MONTH) 

    // Or, for that month 
    //new CronExpression("0 0 0 L JAN-DEC ? *"); 
} 
+4

使用L(或任何其他變體L-X)沒有在我的處境有所幫助。用戶可以指定首次運行作業的任何開始日期。這個開始日期的月份必須用來每月運行工作。所以,它可以是1-31。問題在於29-31,因爲不是所有的月份都有。因此,如果用戶選擇Janurary 30日,則工作必須在2月29日,3月30日,4月30日等運行。 3月28日,使用L-3將在2月25日(非閏年)觸發 - 但這不是我所需要的。作業必須在指定的日期或上一個最近的日期運行。 – ilu 2012-07-12 18:52:33

0

試試這個片段,它創建1至3個觸發器(套一整年)取決於一天:

 Set<Trigger> triggers = new HashSet<>(3); 

     CronScheduleBuilder interval = CronScheduleBuilder.monthlyOnDayAndHourAndMinute(dayNumber, 0, 0); 

     if (dayNumber > 28) { 
      CronTrigger trigger28 = TriggerBuilder.newTrigger() 
        .withIdentity("payment_trigger28_" + merchantServiceTemplate.getId(), "payment_triggers") 
        .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 28 2 ? *")) 
        .endAt(merchantServiceTemplate.getEndScheduleDate()) 
        .build(); 
      triggers.add(trigger28); 

      if (dayNumber == 31) { 
       CronTrigger trigger30 = TriggerBuilder.newTrigger() 
         .withIdentity("payment_trigger30_" + merchantServiceTemplate.getId(), "payment_triggers") 
         .withSchedule(CronScheduleBuilder.cronSchedule("0 0 0 30 4,6,9,11 ? *")) 
         .endAt(merchantServiceTemplate.getEndScheduleDate()) 
         .build(); 
       triggers.add(trigger30); 
      } 
     } 

     Trigger trigger = TriggerBuilder.newTrigger() 
       .withIdentity("payment_triggerAll_" + merchantServiceTemplate.getId(), "payment_triggers") 
       .withSchedule(interval) 
       .endAt(merchantServiceTemplate.getEndScheduleDate()) 
       .build(); 
     triggers.add(trigger); 


     scheduler.scheduleJob(job, triggers, false); 
0

如前所述,您必須爲月份中的每個天數情況創建多個CronExpressions,併爲每個情況創建一個觸發器,然後將所有觸發器添加到所需的Job中。

這是我的版本:

CronExpressions創作:我在二月的cron使用「L」,否則你將不得不在閏年的錯誤

public static List<CronExpression> getCronExpressionList(int seconds, int minutes, 
      int hours, int dayInMonth, Month month, 
      DayOfWeek dayOfWeek) { 
    final String monthsWith30Days = Month.APR + "," + Month.JUN + "," 
        + Month.SEP + "," + Month.NOV; 
    List<CronExpression> crons = new LinkedList<CronExpression>(); 

    String timeString = String.format(("%s %s %s "), seconds, minutes, 
        hours, 0, 0, 0); 
    String dateString = "%s %s %s"; 
    String cron = null; 

    cron = timeString + String.format(dateString, dayInMonth, "*", "?"); 
    crons.add(new CronExpression(cron)); 
    if (dayInMonth > 28) { 
     String febCron = timeString + getFebruarLastDayDateString(dateString); 
     crons.add(new CronExpression(febCron)); 
     if (dayInMonth == 31) { 
      String monthsWithThirtyDaysCron = timeString + String.format(dateString, 
        "L", monthsWith30Days, "?"); 
      crons.add(new CronExpression(monthsWithThirtyDaysCron)); 
     } 
    } 
    return crons; 
} 

private static String getFebruarLastDayDateString(String initialCron) 
       throws ParseException { 
    return String.format(initialCron, "L", Month.FEB, "?"); 
} 

留意。

創建觸發器:

 Set<CronTrigger> triggers = new HashSet<>(); 

     int i = 1; 
     for (CronExpression cronEx : cronsList) { 
      CronTrigger trigger = newTrigger() 
        .withIdentity("trigger" + i, groupName) 
        .withSchedule(cronSchedule(cronEx)) 
        .build(); 
       triggers.add(trigger); 
       i++; 
     } 
相關問題