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
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.
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.
I am not very familiar with Groovy library but since Groovy is running on JVM we then I suppose you should be able to use Java / Scala library as well.
What you need here is a professional schedule generation library like Lamma(http://lamma.io) instead of a general purpose date time library like 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());