2010-10-20 25 views
10

Tôi đang làm việc trên ứng dụng loại lịch Groovy/Java cho phép người dùng nhập các sự kiện có ngày bắt đầu và lặp lại tùy chọn. Nếu đó là một sự kiện lặp đi lặp lại, nó có thể recurr:logic sự kiện định kỳ

  • hàng tháng vào một ngày của tháng tương ứng với ngày bắt đầu
  • hàng tuần vào một ngày trong tuần của tương ứng với ngày bắt đầu
  • mỗi 2 tuần vào một ngày trong tuần của tương ứng với ngày bắt đầu
  • , vv

tôi dự kiến ​​ban đầu về cách sử dụng API của Google lịch để làm tất cả các logic tái phát, nhưng nó được chứng minh là một Pita khổng lồ , vì lý do Tôi sẽ thảo luận thêm nếu có ai quan tâm.

Vì vậy, bây giờ, tôi đã quyết định cuộn giải pháp của riêng mình. Cho một ngày, tôi muốn tìm hiểu xem một sự kiện lặp lại xảy ra vào ngày này hay không. Logic của tôi (trong giả) sẽ như sau:

public boolean occursOnDate(def date, def event) { 

    def firstDate = event.startDate 

    if (firstDate > date) { 
    return false; 

    } else if (event.isWeekly()) { 
    return event.dayOfWeek() == date.dayOfWeek() 

    } else if (event.isMonthly()) { 
    return event.dayOfMonth() == date.dayOfMonth() 

    } else { 
    // At this point we know the event occurs every X weeks where X > 1 
    // Increment firstDate by adding X weeks to it as many times as possible, without 
    // going past date 
    return firstDate == date 
    } 
} 

Logic này có vẻ hợp lý, nhưng thực tế sẽ được khá nhiều công sức để thực hiện khi bạn xem xét tất cả các trường hợp cạnh lạ (ví dụ như làm thế nào để xử lý một định kỳ hàng tháng sự kiện vào tháng 2 có lần xuất hiện đầu tiên là ngày 31 tháng 1).

Có thư viện nào có thể giúp tôi triển khai tính năng này không? Một số chi tiết cụ thể sẽ được đánh giá cao (ví dụ: không có tín dụng nào sẽ được trao cho "Sử dụng Thời gian Joda").

Cảm ơn, Don

+0

câu hỏi tương tự: [Whats tốt nhất ngày java tái phát mẫu máy tính] (http://stackoverflow.com/q/492055/642706) –

+0

giấy Martin Fowler này, [sự kiện lặp lại cho Lịch] (http://martinfowler.com/apsupp/recurring.pdf) có thể hữu ích. –

Trả lời

2

Tôi không biết gì về Groovy, và đề nghị đầu tiên của tôi sẽ là Joda, nhưng bạn biết về nó.

Tôi biết điều này có vẻ quá mức cần thiết cho bạn và thậm chí không thể áp dụng, nhưng Quartz Scheduler xử lý tất cả các quy tắc liên quan đến sự kiện và lặp lại này khá tốt. Bạn không thể sử dụng khả năng lên lịch của nó và chỉ cần sử dụng các lớp Trình kích hoạt (như CronTrigger) để tính ngày sự kiện cho bạn.

Liên kết CronTrigger trên cho thấy một số ví dụ về biểu thức mà bạn có thể sử dụng để xử lý sự kiện của bạn, giống như hoàn cảnh đặc biệt khó chịu này: "0 0 12 L *"

- kích hoạt sự kiện vào giữa ngày mỗi ngày cuối cùng của tháng (không bị đau đầu với những năm nhuận và như vậy)

Vấn đề về thời gian tiết kiệm ánh sáng ban ngày cũng được xử lý.

Đối với các mã, tạo ra các kích hoạt với sự tái mong muốn và sau đó bạn có thể trích xuất tất cả các lần bắn bạn muốn:

Date firstFireTime = myTrigger.getNextFireTime(); 
... 
while (...) { 
    Date nextFireTime = myTrigger.getFireTimeAfter(previousFireTime); 
    ... 
} 

Hy vọng điều này có thể hữu ích.

+0

Nếu bạn có một số thông tin cụ thể hơn về cách tôi có thể sử dụng Joda/Quartz để đạt được mục tiêu của mình, tôi rất muốn nghe nó. –

+0

Đã thêm thông tin khác ở trên :) – mdrg

8

Loại quy tắc lặp lại bạn muốn được chỉ định hợp lý trong RFC-2445 (về cơ bản, thông số iCal). Bắt minutiae của chính xác này có thể được khá tham gia. Tôi khuyên bạn nên sử dụng thư viện google-rfc-2445 cho việc này hoặc triển khai thực hiện thông số đó khác như iCal4J.

0

Tôi không quen thuộc với thư viện Groovy nhưng kể từ khi Groovy đang chạy trên JVM, chúng tôi giả sử bạn cũng có thể sử dụng thư viện Java/Scala.

Những gì bạn cần ở đây là thư viện tạo lịch biểu chuyên nghiệp như Lamma (http://lamma.io) thay vì thư viện thời gian có mục đích chung như Joda.

// monthly on a date of the month that corresponds to the start date 
    // output: [Date(2014,6,10), Date(2014,7,10), Date(2014,8,10), Date(2014,9,10), Date(2014,10,10)] 
    System.out.println(Dates.from(2014, 6, 10).to(2014, 10, 10).byMonth().build()); 

    // weekly on a day of the week of that corresponds to the start date 
    // output: [Date(2014,6,10), Date(2014,6,17), Date(2014,6,24), Date(2014,7,1), Date(2014,7,8)] 
    System.out.println(Dates.from(2014, 6, 10).to(2014, 7, 10).byWeek().build()); 

    // every 2 weeks on a day of the week of that corresponds to the start date 
    // output: [Date(2014,6,10), Date(2014,6,24), Date(2014,7,8)] 
    System.out.println(Dates.from(2014, 6, 10).to(2014, 7, 10).byWeeks(2).build()); 

    // edge cases are handled properly, for example, leap day 
    // output: [Date(2012,2,29), Date(2013,2,28), Date(2014,2,28), Date(2015,2,28), Date(2016,2,29)] 
    System.out.println(Dates.from(2012, 2, 29).to(2016, 2, 29).byYear().build()); 
Các vấn đề liên quan