2010-04-26 17 views
6

Có cách nào trong Java để tìm "Thời gian kích hoạt lần cuối" từ biểu thức Cron hay không.Tìm thời gian đã qua sử dụng Biểu thức Cron trong Java

Ví dụ: Nếu bây giờ = 25 tháng 4 năm 2010 10 giờ chiều, biểu thức cron "0 15 10? * *" (Thạch anh) sẽ trả lại cho tôi 25-Apr-2010 10:15 am

Lưu ý: 1) Tôi không quan tâm nếu chúng tôi sử dụng các biểu thức cron tiêu chuẩn (như Unix và Quartz) hoặc ít phổ biến hơn nếu chúng có thể tìm nạp chính xác "Last Fired Time" 2) Ngoài ra nó không có nghĩa là "Last Fire time" vì trigger có thể không kích hoạt, nhưng về mặt logic thì nên là một cách để nói khi nào nó (sẽ có) bắn cuối cùng.

Trả lời

2

Trước tiên, tôi không biết thư viện hiện có hỗ trợ điều này. Thạch anh có thể, nhưng các thư viện lớp Java tiêu chuẩn chắc chắn không.

Thứ hai, nói đúng những gì bạn yêu cầu ban đầu được yêu cầu là không thể. Tốt nhất mà thư viện có thể cho bạn biết là biểu thức cron sẽ có hoặc nên có được kích hoạt. Điều duy nhất có thể (về mặt lý thuyết) cho bạn biết lần cuối cùng một biểu thức cron thực sự được kích hoạt là bản thân lịch trình.

+0

Xin chào Stephen, Cảm ơn bạn đã phản hồi. Tôi đã thêm một chút thông tin trong ghi chú của câu hỏi của mình để giải quyết vấn đề của mình. –

1

Quartz dường như có một số hỗ trợ thư viện cho các biểu thức cron.

Xem the Javadoc for the CronExpression class, có phương thức được gọi là getTimeBefore. I.e.,

CronExpression cron = new CronExpression("0 15 10 ? * *"); 
Date today = new Date(); 
Date previousExecution = cron.getTimeBefore(today); 

Nó có thể phụ thuộc vào phiên bản Quartz cho dù có hoạt động hay không.

Nhìn vào nguồn mới nhất (phiên bản 2.1.0 tại thời điểm viết) phương pháp này chưa được triển khai và luôn trả về giá trị rỗng.

2

Một giải pháp mà tôi đã tìm thấy với Quartz là quay lại một khoảng thời gian cho trình kích hoạt và tính toán thời gian kích hoạt tiếp theo. Bằng cách lặp qua tất cả các trình kích hoạt thời gian gần đây nhất mà một trình kích hoạt nên đã kích hoạt trong quá khứ có thể được xác định.


Tính khoảng cách giữa mỗi bắn:

Date nextFireTime = trigger.getNextFireTime(); 
Date subsequentFireTime = trigger.getFireTimeAfter(nextFireTime); 
long interval = subsequentFireTime.getTime() - nextFireTime.getTime(); 

Tìm lần bắn tiếp theo cho một thời gian cho đến khi khoảng thời gian trong quá khứ:

Date previousPeriodTime = new Date(System.currentTimeMillis() - interval); 
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime); 

Tôi đã tìm thấy rằng nếu bạn đang sử dụng a CronTrigger điều này ngăn cản bạn yêu cầu một thời gian cháy trong quá khứ. Để làm việc xung quanh này tôi sửa đổi thời gian bắt đầu, vì vậy đoạn trên trở thành:

Date originalStartTime = trigger.getStartTime(); // save the start time 
Date previousPeriodTime = new Date(originalStartTime.getTime() - interval); 
trigger.setStartTime(previousPeriodTime); 
Date previousFireTime = trigger.getFireTimeAfter(previousPeriodTime); 
trigger.setStartTime(originalStartTime); // reset the start time to be nice 

Duyệt qua tất cả các trigger và tìm ra một trong đó là gần đây nhất là trong quá khứ:

for (String groupName : scheduler.getTriggerGroupNames()) { 
    for (String triggerName : scheduler.getTriggerNames(groupName)) { 
     Trigger trigger = scheduler.getTrigger(triggerName, groupName); 
     // code as detailed above... 
     interval = ... 
     previousFireTime = ... 
    } 
} 

tôi sẽ để nó như một bài tập cho người đọc để cấu trúc lại nó thành các phương thức hoặc các lớp trợ giúp. Tôi thực sự sử dụng thuật toán trên trong trình kích hoạt ủy nhiệm được phân lớp mà sau đó tôi đặt trong một tập hợp được sắp xếp theo thời gian kích hoạt trước đó.

+2

Sự khác biệt giữa các đám cháy tiếp theo sẽ không giống nhau. – Ahamed

0
public class CronMircoUtils { 

    /** 
    * Use this method to calculate previous valid date for cron 
    * @param ce CronExpression object with cron expression 
    * @param date Date for find previous valid date 
    * @return 
    */ 
    public static Date getPreviousValidDate(CronExpression ce, Date date) { 
     try { 
      Date nextValidTime = ce.getNextValidTimeAfter(date); 
      Date subsequentNextValidTime = ce.getNextValidTimeAfter(nextValidTime); 
      long interval = subsequentNextValidTime.getTime() - nextValidTime.getTime(); 
      return new Date(nextValidTime.getTime() - interval); 
     } catch (Exception e) { 
      throw new IllegalArgumentException("Unsupported cron or date", e); 
     } 
    } 
} 

Source Code trong https://github.com/devbhuwan/cron-micro-utils

+0

Điều này sẽ chỉ hoạt động đối với pháo nổ định kỳ. Điều gì sẽ xảy ra khi không có 'nextNextValidTime' hoặc khi bị cháy không đều (ví dụ: cháy ở phút 10, 12, 11, 17, 37)? –

2

cron-utils là một mã nguồn mở thư viện Java để phân tích, xác nhận, di chuyển crons hỗ trợ các hoạt động mà bạn cần. Để có được ngày trước đó từ một cron trước thời gian cụ đơn giản:

//Get date for last execution 
DateTime now = DateTime.now(); 
ExecutionTime executionTime = ExecutionTime.forCron(parser.parse("* * * * * * *")); 
DateTime lastExecution = executionTime.lastExecution(now)); 

Gấu nhớ rằng trong tình trạng hiện tại của nó là một lỗi bit và có thể không tính toán một cách chính xác cho các biểu thức cron phức tạp hơn.

+0

hi Joao, Điều này làm việc ngay cả khi công việc không chạy (ví dụ: máy chủ ngoại tuyến)? – Marin

+1

@NunoMarinho Có, điều này chỉ đơn giản là tính toán ngày trước đó từ một biểu thức cron. Bản thân thư viện không biết gì về những gì bạn đang làm với biểu thức cron. Thư viện này không lên lịch các hành động hoặc công việc được thực thi, nó chỉ tính toán các ngày dựa trên các biểu thức cron. Tôi đã không sử dụng thư viện này trong một thời gian dài mặc dù, hãy chắc chắn rằng nó phù hợp với nhu cầu của bạn và kiểm tra kỹ lưỡng ứng dụng của bạn sau khi sử dụng nó. –

+0

Obrigado João: D – Marin

0

Trong trường hợp bạn đang sử dụng org.quartz, có thể sử dụng context.getPreviousFireTime();

Ví dụ:

public class TestJob implements Job { 

    @Override 
    public void execute(JobExecutionContext context) throws JobExecutionException { 

     context.getPreviousFireTime(); 
    } 
} 

Nếu bạn đang sử dụng context.getTrigger().getPreviousFireTime(), bạn sẽ có thời gian kích hoạt của công việc đang chạy tại khoảnh khắc.

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