Sum of intervals using Joda

Goal

You have a list of date periods that you want to sum so that you have the whole duration of all those periods, using Java

Description

In a given application, you have a requirement to sum the duration of a set of date periods (which are or may be represented as Joda time Intervals). You need to be careful with date overlaps too, meaning that, for instance, if you have one period starting in 2013-01-01 to 2013-01-30 and another period is contained in that period, for instance, 2013-01-13 to 2013-01-20, only the biggest time period should be taken into account

How to

I started this implementation with a logic that would iterate through all original intervals, to filter them so that the new intervals set would contain only the intervals that should be taken into account to sum their corresponding durations, i.e., completely contained intervals would be removed from the resulting list, where overlapped intervals would increase existing intervals, either through making the start date become earlier or making the end date become later, according to each interval pairs. However, a much simple solution is to always sum up the intervals and subtract the overlaps of those intervals (only when they overlap each other, of course, because when that does not occur, the overlap is 0)

Therefore, the implementation was as simple as:

public Period getDuration(final List intervals) {
  Duration duration = null;
  Interval previousInterval = null;
  for (final Interval interval : intervals) {
    if (duration == null) {
      duration = interval.toDuration();
    } else {
      duration = duration.plus(interval.toDuration());
      if (previousInterval.overlaps(interval)) {
        final Duration overlapDuration = previousInterval.overlap(interval).toDuration();
        duration = duration.minus(overlapDuration);
      }
    }
    previousInterval = interval;
  }
  return duration.toIntervalFrom(new DateMidnight()).toPeriod(PeriodType.yearMonthDay());
}

Notice the last part of the method’s implementation where the calculated duration (which, by definition, is not aware of any specific period interval) has been contextualized into the current date so that it may be converted into a period that knows exactly how to calculate the duration, starting in a specific date.

Explanations

This implementation, which was suggested by Linkare’s CTO, José Pedro Pereira has proven useful, simple and effective. One smart algorithm, together with Joda, can really take us there…

4 comments

  1. I would just make a slighte change… and that would be here:

    if (duration == null) {
    duration = interval.toDuration();
    } else if(previousInterval.overlaps(interval) && !(previousInterval.contains(interval) || interval.contains(previousInterval))) {
    duration = duration.plus(previousInterval.overlap(interval).toDuration());
    } else {
    duration = duration.plus(interval.toDuration());
    }

    That way i would avoid several times the more complex operations by just doing boolean ones. The solution that was presented ad an adition and a subtraction of the same amount when one interval was contained in other. I think those would be unecessary operations on the containing intervals case ans this way the execution would be faster(i think…).

    The code is made by head so it can have execution errors, but i think the idea is there.

    1. Hello Nuno,

      Thank you for your comment. However, if I am not mistaken, there is one problem with the solution you have proposed. Basically, if two intervals overlap each other and one of them is contained in the other, then you will sum the intervals (because it will go to the else statement), which is wrong, because only one of them should be taken into account. Right?

      In terms of speed, I haven’t measured and compared any of the solutions but maybe you are right… However, IMO, this second solution is a little bit trickier to understand, but that’s a matter of taste 🙂

      1. You are right when you say there is an error on my proposal, and i rapidly realised that. And to take that situation into acount the code would be even trickier… to many if’s, and’s and or’s… The question here is if the gain in speed is significant enough to consider the loss of readability to the human eye. When i post the proposal i thought it was… Now i’m not that convinced. 🙂

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s