views:

56

answers:

2

Hi,

I'm working on a Groovy/Java calendar-type application that allows the user to enter events with a start date and an optional recurrence. If it's a recurring event, it may recurr:

  • monthly on a date of the month that corresponds to the start date
  • weekly on a day of the week of that corresponds to the start date
  • every 2 weeks on a day of the week of that corresponds to the start date
  • etc.

I originally planned on using the Google calendar API to do all the recurrence logic, but it proved to be an enormous PITA, for reasons I'll discuss further if anyone cares.

So now, I've decided to roll my own solution. Given a date, I want to figure out whether a recurring event occurs on this date. My logic (in pseudocode) will be as follows:

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

This logic seems reasonable, but will actually be quite a lot of effort to implement when you consider all the weird edge cases (e.g. how to handle a monthly recurring event in February whose first occurrence is Jan 31).

Is there a library that can take help me to implement this? Some specifics would be much appreciated (e.g. no credit will be awarded for "Use Joda Time").

Thanks, Don

+2  A: 

I know nothing about Groovy, and my first suggestion was going to be Joda, but you know about it.

I know this may seem overkill for you, and maybe even not applicable, but Quartz Scheduler handles all this recurrence and events related rules pretty well. You could not use its scheduling capabilities, and just use the Trigger classes (like CronTrigger) to calculate the event dates for you.

The CronTrigger link above shows some examples of expressions you could use to handle your events, like this particularly nasty situation:

"0 0 12 L * ?" - trigger an event at mid day every last day of the month (no headaches with leap years and such)

Daylight saving time issues are handled as well.

As for the code, create the trigger with the desired recurrence and then you may extract all the firing times you wish:

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

Hope this can be useful.

mdrg
If you have some more specific information about how I can use Joda/Quartz to achieve my objective, I'd love to hear it.
Don
Added further info above :)
mdrg
+2  A: 

The sort of recurrence rules you want are reasonably well specified in RFC-2445 (basically, the iCal spec). Getting the minutiae of this correct can be pretty involved. I'd suggest using the the google-rfc-2445 library for this, or another implementation of that spec like iCal4J.

GaryF