codinguser codinguser - 3 months ago 15
Java Question

How to calculate number of event occurrences with Joda Time?

Given an example event recurrence schedule which is defined as follows:


StartTime: Monday, 2016-June-06 09:00H
EndTime: Monday, 2016-August-29 10:00H
Period: Bi-weekly


This means, every 2 weeks on Monday at 09:00H, until 29th August 2016. However the endTime is on a Monday, 29th August, which is just at the beginning of the new week, but should be included in the schedule (because it ends at 10:00H). So I expect 7 occurrences of the event.

Conversely, if the endTime were 08:00H on 29th August, then I would expect only 6 occurrences of the event.

Right now, I calculate number of occurrences using Joda Time as such:
Weeks.weeksBetween(startTime, endTime).dividedBy(multiplier).getWeeks()


Of course, this gives me only 6 occurrences instead of 7, because there are really only 12 weeks in the time duration and the last occurrences is on the Monday after the last week (ending on Sunday). So that does not count as full week. The same goes for any other kinds of schedules - months, days, years etc.

How can I reliably calculate number of occurrences of an event between two times?

Thanks

Answer

Using pseudo-code, as I with Yoda not too familiar I am:

  1. counter = 1, someDate = start time, increment = two weeks
  2. loop: someDate = someDate + increment
  3. if someDate < end time: then counter++ else break loop

Alternatively, for the people that don't like looping:

  1. Compute the exact number of hours between start date and end date
  2. Figure how often 24 * 7 * 2 would fit into the aforementioned number of hours

Sample code using JodaTime library:

int multiple = 2; //or whatever periodicity is needed
ReadablePeriod jodaPeriod;
switch (mPeriodType){
    case DAY:
        jodaPeriod = Days.days(multiple);
        break;
    case WEEK:
        jodaPeriod = Weeks.weeks(multiple);
        break;
    case MONTH:
        jodaPeriod = Months.months(multiple);
        break;
    case YEAR:
        jodaPeriod = Years.years(multiple);
        break;
    default:
        jodaPeriod = Months.months(multiple);
}
int count = 0;
LocalDateTime startTime = new LocalDateTime(mPeriodStart.getTime());
while (startTime.toDateTime().getMillis() < mPeriodEnd.getTime()){
    ++count;
    startTime = startTime.plus(jodaPeriod);
}
return count;
Comments