Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Make a union of two Joda-Time Interval objects

In Joda-Time, is there any way to create a Interval as a union of two other intervals. I know there is intersection method which is called overlap (and overlaps). But I can not see any union methods.

like image 895
serge Avatar asked Dec 27 '13 18:12

serge


2 Answers

If you want an interval that "covers" two others, just create a new interval that runs from min(a.start, b.start) to max(a.end, b.end).

If you need to represent the gap as well, then you'll need to write your own classes to handle the behavior you want. There's nothing builtin to Joda-time for this as there are several possible interpretations of what it means to "union" non-contiguous intervals.

like image 198
Jim Garrison Avatar answered Nov 10 '22 10:11

Jim Garrison


The answer by Jim Garrison is correct, but brief. I decided to try an implementation. Using Joda-Time 2.3 with Java 7 on a Mac.

If you made much use of this kind of "union" method, perhaps you should consider creating a subclass of Interval to add a method where you pass a single (second) Interval to be compared to the first, the one whose method is being called.

For occasional use, a static method stuck away on some utility class would suffice. That's what I wrote here, a static method where you pass a pair of Intervals. A new Interval is returned.

Rather than use multiple-line if statements, my example code uses the ?: ternary operator to collapse to one line the decision to pull the first or second DateTime.

Static method…

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.

static Interval union( Interval firstInterval, Interval secondInterval ) 
{
    // Purpose: Produce a new Interval instance from the outer limits of any pair of Intervals.

    // Take the earliest of both starting date-times.
    DateTime start =  firstInterval.getStart().isBefore( secondInterval.getStart() )  ? firstInterval.getStart() : secondInterval.getStart();
    // Take the latest of both ending date-times.
    DateTime end =  firstInterval.getEnd().isAfter( secondInterval.getEnd() )  ? firstInterval.getEnd() : secondInterval.getEnd();
    // Instantiate a new Interval from the pair of DateTime instances.
    Interval unionInterval = new Interval( start, end );

    return unionInterval;
}

Example usage…

// © 2013 Basil Bourque. This source code may be used freely forever by anyone taking full responsibility for doing so.
// import org.joda.time.*;
// import org.joda.time.format.*;

// Note the various time zones.
Interval i1 = new Interval( new DateTime( 2013, 1, 1, 0, 0, 0, DateTimeZone.forID( "America/Montreal" ) ), new DateTime( 2013, 1, 5, 0, 0, 0, DateTimeZone.forID( "America/Montreal" ) ) );
Interval i2 = new Interval( new DateTime( 2013, 1, 10, 0, 0, 0, DateTimeZone.forID( "Europe/Paris" ) ), new DateTime( 2013, 1, 15, 0, 0, 0, DateTimeZone.forID( "Europe/Paris" ) ) );

Interval i3 = TimeExample.union( i1, i2 );

Dump to console…

System.out.println("i1: " + i1 );
System.out.println("i2: " + i2 );
// Note that Joda-Time adjusts the ending DateTime's time zone to match the starting one.
System.out.println("i3: " + i3 );

When run…

i1: 2013-01-01T00:00:00.000-05:00/2013-01-04T18:00:00.000-05:00
i2: 2013-01-10T00:00:00.000+01:00/2013-01-15T00:00:00.000+01:00
i3: 2013-01-01T00:00:00.000-05:00/2013-01-14T18:00:00.000-05:00
like image 23
Basil Bourque Avatar answered Nov 10 '22 12:11

Basil Bourque