2014-09-24 24 views
8

Tôi có thể sử dụng Quartz Scheduler thư viện để tạo ra lịch trình với các thiết lập sau đây ?:Tôi có thể sử dụng Quartz Scheduler để bắn mỗi tháng vào ngày thứ 30 nhưng nếu tháng không có ngày thứ 30, lửa vào ngày cuối cùng?

  • Bắt đầu từ Đéc, 30 năm 2014
  • Execute mỗi ngày 30
  • Mỗi tháng 2 do
  • Nếu tháng không có ngày thứ 30, hành động sẽ diễn ra vào ngày ngày cuối cùng của tháng.

Vì vậy, lịch trình kết quả sẽ là:

  • 30 tháng 12 năm 2014
  • tháng hai năm 2015
  • 30 Tháng 4 2015
  • ... và vân vân

Từ những gì tôi đã học:

  1. CronTrigger không cho phép làm như vậy (nó có thể được thiết lập chỉ được kích hoạt trên tháng cụ thể và không phải trên khoảng),
  2. CalendarIntervalTrigger sẽ bỏ qua tháng mà không có ngày thứ 30 (kích hoạt thông tạo ra bởi mã sau)

    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(); 
    } 
    

Nếu không, là có bất kỳ lựa chọn thay thế (nó nên làm việc trên JBoss eap 6.2.0)?

+3

Thực hiện tối thiểu: kích hoạt công việc hàng ngày, kiểm tra xem ngày có hợp lệ khi bắt đầu công việc hay không. Tôi không biết thực tế trong trường hợp của bạn (chi phí thiết lập và tương tự), nhưng nó sẽ cho phép bạn sử dụng API ngày, di chuyển logic ngày chính xác sang phương pháp, tài liệu và kiểm tra nó, v.v. – ssube

Trả lời

5

Bạn có thể đạt được điều này trong Quartz nhưng bạn phải xoay hành vi bình thường bằng cách sử dụng CalendarIntervalTrigger để kích hoạt Công việc tính toán khi Công việc 'thực' của bạn được lên lịch.

Bạn sắp xếp một kích hoạt mà bắn mỗi ngày 1 tháng lập kế hoạch của bạn:

[...] 
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); 

Và trong SchedulingCalculationJob Job, bạn tính toán 'thực tế' ngày lịch công việc của bạn:

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); 
    } 
} 

Đó là một chút sioux nhưng tôi đã sử dụng nó và tôi làm việc tốt.

+0

Đẹp nhất! Upvoting, coz bây giờ tôi có một cái gì đó để dính vào :). Tôi nghĩ có thể có nhiều cách "lên kế hoạch" để thực hiện điều này mà không cần tính toán thêm hoặc một số phương pháp Quartz để thêm ngày cụ thể vào CalendarIntervalTrigger ... Tôi sẽ đợi một thời gian và nếu không, tôi sẽ chấp nhận câu trả lời của bạn. – n1k1ch

+1

Tôi tăng cường mã một chút, bạn sẽ chỉ cần truy xuất chi tiết công việc 'thực tế' và tham chiếu lịch biểu trong phương thức 'thực hiện' và phần còn lại sẽ hoạt động;) – Kraiss

+0

chúng ta có thể chỉ định ngày kết thúc ở đâu đó không ??? cho đến khi nó sẽ kích hoạt ??? – Elizabeth

Các vấn đề liên quan