Joda-Time
Joda-Time and its Interval class with the overlap
method is just what you need. Very easy.
Time Zone
Unlike java.util.Date, a DateTime truly knows its assigned time zone. Generally better to specify than rely on default. Note that if you are tracking date+time (a DateTime rather than a LocalDate), then time zone is critical. The definition of a "day" beginning and ending depends on time zone. Businesses that work across time zones may choose to use UTC for this purpose.
Span of Time
FYI, besides Interval, Joda-Time also offers the Period and Duration classes for working with a span of time.
Start of Day
When working with date-time values but focusing on a "day", then adjust the time portion to the first moment of the day for that particular time zone. In Joda-Time, simply call the withTimeAtStartOfDay
method.
Avoid the "midnight"-related classes and methods. They are no longer recommended by the Joda-Time team.
Half-Open
Joda-Time uses the "Half-Open" approach when comparing spans of time. The beginning in inclusive and the ending is exclusive. That means since you want from December 1 to March 31 that we define an Interval of the first moment of the day of December 1
to the first moment of the day of April 1
. If you ponder this, and search StackOverflow for other postings on "joda interval", you'll come to see the wisdom of this approach.
Comparison
The Interval class offers handy comparison methods: contains
, abuts
, overlap
, and gap
. Be sure to read the doc to understand exact details.
java.time
Java 8 brings the new java.time package, inspired by Joda-Time, defined by JSR 310. Joda-Time continues to work in Java 8, but you may want to learn java.time rather than Joda-Time if you are new to date-time work.
Example Code
DateTimeZone timeZone = DateTimeZone.forID( "Europe/Budapest" ); // Or, perhaps DateTimeZone.UTC
// Inputs
DateTime contractStart = new DateTime( 2014, 1, 2, 0, 0, 0, timeZone );
DateTime contractStop = new DateTime( 2014, 5, 6, 0, 0, 0, timeZone );
Interval contractInterval = new Interval( contractStart, contractStop );
// Target to test
DateTime targetStart = new DateTime( 2013, DateTimeConstants.DECEMBER, 1, 0, 0, 0, timeZone );
DateTime targetStop = targetStart.plusMonths( 4 );
Interval targetInterval = new Interval( targetStart, targetStop );
boolean targetContainsContract = targetInterval.contains( contractInterval );
boolean targetOverlapsContract = ( targetInterval.overlap( contractInterval ) != null );
Dump to console…
System.out.println( "contractInterval: " + contractInterval );
System.out.println( "targetInterval: " + targetInterval );
System.out.println( "targetContainsContract: " + targetContainsContract );
System.out.println( "targetOverlapsContract: " + targetOverlapsContract );
When run…
contractInterval: 2014-01-02T00:00:00.000+01:00/2014-05-06T00:00:00.000+02:00
targetInterval: 2013-12-01T00:00:00.000+01:00/2014-04-01T00:00:00.000+02:00
targetContainsContract: false
targetOverlapsContract: true