Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

Accessibility testing is a crucial aspect to ensure that your application is usable for everyone and meets accessibility standards that are required in many countries.

By automating these tests, teams can quickly detect issues related to screen reader compatibility, keyboard navigation, color contrast, and other aspects that could pose a barrier to using the software effectively for people with disabilities.

Learn how to automate accessibility testing with Selenium and the LambdaTest cloud-based testing platform that lets developers and testers perform accessibility automation on over 3000+ real environments:

Automated Accessibility Testing With Selenium

1. Introduction

In various applications such as appointments, bookings, or project timelines, avoiding scheduling conflicts is paramount. Overlapping dates can lead to inconsistencies and errors. In this tutorial, we’ll explore different scenarios of date range overlap and dive into various approaches and formulas to check for overlaps.

2. Understanding Overlapping Date Ranges

Before we dive into the implementation, let’s ensure a clear understanding of what it means for two date ranges to overlap. Understanding the different scenarios that constitute date range overlap is crucial when implementing an efficient and accurate overlap checker. Let’s break down the various scenarios that need to be considered.

2.1. Partial Overlap

Partial overlap occurs when one date range partially overlaps with another. This happens when two ranges share some portion of their timeframe but don’t entirely encompass each other. For example, if Project A spans from January 1st to February 10th and Project B runs from February 5th to March 1st, they partially overlap:

A                            B
|-----------------------------|
                C                                D
                |--------------------------------|

2.2. Full Overlap

Full overlap happens when one date range entirely encompasses another. This occurs when one date range completely falls within the boundaries of another. For example, if Booking A covers July 1st to July 31st and Booking B covers July 15th to July 25th, Booking B completely overlaps with Booking A:

A                                               B
|------------------------------------------------|
                C                      D
                |----------------------|

2.3. Consecutive Ranges

Two ranges are considered adjacent if one ends immediately before the other begins. This is common in project timelines, where Project X spans from March 1st to March 31st, and Project Y runs from April 1st to April 30th. These ranges are adjacent but not overlapping:

A                    B
|---------------------|
                       C                    D
                       |--------------------|

2.4. Zero-Range Duration and Consecutive Ranges

Zero-range duration refers to a scenario where the start and end dates of a range are the same, resulting in a duration of zero. For example, we may encounter an event scheduled for exactly one day with no duration. Although seemingly a special case, handling this scenario explicitly is essential to ensure the correctness of our date range overlap logic when considering consecutive ranges:

A                    B
|---------------------|
                      CD
                      |

3. Overlapping Formulas

Various mathematical formulas encapsulate the logic for determining date range overlap. Here, we’ll explore three commonly used formulas and explain their underlying principles.

Let’s first define the variables used in the formulas:

  • A: Start date of the first date range
  • B: End date of the first date range
  • C: Start date of the second date range
  • D: End date of the second date range

3.1. Calculating the Overlap Duration

This formula calculates the overlap duration by subtracting the earlier ending date from the later starting date:

(min(B, D) - max(A, C)) >= 0

If this duration is negative, there’s no overlap. If it’s zero, the ranges might be touching, or one might be a single point in time. The application should consider whether to treat this scenario as an overlap or not. Moreover, a positive duration tells us there’s an overlap.

3.2. Checking for Non-Overlap Conditions

This formula checks for non-overlapping conditions between two date ranges. If either condition fails, then there’s an overlap:

!(B <= C || A >= D)

Take note that if we change the condition to use strict inequality “<” and “>”, it means the ranges must not touch at all. There should be no common point between the two ranges. Once again, the application should decide whether to treat this scenario as an overlap or not.

3.3. Finding Minimum Overlap

This implementation calculates the overlap duration in days by considering the minimum of the four calculations. If the minimum overlap duration is zero or negative, it implies that there is no overlap, as the ranges do not intersect in a non-zero duration. A positive minimum overlap duration indicates an actual overlap, suggesting that the ranges share a duration greater than zero:

min((B - A), (B - C), (D - A), (D - C)) >= 0

However, if we change it to just greater than zero, the condition becomes stricter. This means there must be more than just a touch at a single point and must be a non-zero duration of overlap.

4. Implementation

Now that we’ve explored the different overlapping scenarios and formulas, let’s dive into implementing code to accurately detect these overlaps using various approaches.

4.1. Using Calendar

We’ll leverage the Calendar class to manage date ranges and check for overlaps. The Calendar class is part of the java.util package and provides a way to work with dates and times. The getTimeInMillis() method is used to obtain the time in milliseconds for each Calendar instance.

In this example, we’ll leverage the Math.min() and Math.max() methods to calculate the overlap duration by subtracting the earlier ending date from the later starting date:

boolean isOverlapUsingCalendarAndDuration(Calendar start1, Calendar end1, Calendar start2, Calendar end2) {
    long overlap = Math.min(end1.getTimeInMillis(), end2.getTimeInMillis()) -
      Math.max(start1.getTimeInMillis(), start2.getTimeInMillis());
    return overlap > 0;
}

To implement the non-overlap conditions checking, we’ll utilize the before() and after() methods provided by the Calendar class. These methods assess the chronological relationship between date instances and are essential for determining overlap. If either condition is true, it indicates an overlap:

boolean isOverlapUsingCalendarAndCondition(Calendar start1, Calendar end1, Calendar start2, Calendar end2) {
    return !(end1.before(start2) || start1.after(end2));
}

Now, let’s implement the logic using the find minimum formula. This method calculates the minimum overlap duration among different scenarios:

boolean isOverlapUsingCalendarAndFindMin(Calendar start1, Calendar end1, Calendar start2, Calendar end2) {
    long overlap1 = Math.min(end1.getTimeInMillis() - start1.getTimeInMillis(), 
      end1.getTimeInMillis() - start2.getTimeInMillis());
    long overlap2 = Math.min(end2.getTimeInMillis() - start2.getTimeInMillis(), 
      end2.getTimeInMillis() - start1.getTimeInMillis());

   return Math.min(overlap1, overlap2) / (24 * 60 * 60 * 1000) >= 0;
}

To ensure the correctness of our implementation, we can set up test data using Calendar instances representing different date ranges.

First, let’s create the start date range:

Calendar start1 = Calendar.getInstance().set(2024, 11, 15); 
Calendar end1 = Calendar.getInstance().set(2024, 11, 20);

Subsequently, we can set the end date range to partially overlap:

Calendar start2 = Calendar.getInstance()set(2024, 11, 18);
Calendar end2 = Calendar.getInstance().set(2024, 11, 22);

assertTrue(isOverlapUsingCalendarAndDuration(start1, end1, start2, end2));
assertTrue(isOverlapUsingCalendarAndCondition(start1, end1, start2, end2));
assertTrue(isOverlapUsingCalendarAndFindMin(start1, end1, start2, end2));

Here’s the corresponding unit test code to see if the test data is fully overlapping:

Calendar start2 = Calendar.getInstance()set(2024, 11, 16);
Calendar end2 = Calendar.getInstance().set(2024, 11, 18);

assertTrue(isOverlapUsingCalendarAndDuration(start1, end1, start2, end2));
assertTrue(isOverlapUsingCalendarAndCondition(start1, end1, start2, end2));
assertTrue(isOverlapUsingCalendarAndFindMin(start1, end1, start2, end2));

Finally, we set the end date range to consecutive ranges, and we should expect no overlapping:

Calendar start2 = Calendar.getInstance()set(2024, 11, 21);
Calendar end2 = Calendar.getInstance().set(2024, 11, 24);

assertFalse(isOverlapUsingCalendarAndDuration(start1, end1, start2, end2)); 
assertFalse(isOverlapUsingCalendarAndCondition(start1, end1, start2, end2)); 
assertFalse(isOverlapUsingCalendarAndFindMin(start1, end1, start2, end2));

4.2. Using Java 8’s LocalDate

Java 8 introduced the java.time.LocalDate class, which provides a more modern and convenient way to handle dates. We can leverage this class to simplify our date range overlap check. In the calculation of the overlap duration, we utilize the toEpochDay() method provided by the LocalDate class. This method is used to obtain the number of days from the epoch day for a given LocalDate:

boolean isOverlapUsingLocalDateAndDuration(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
    long overlap = Math.min(end1.toEpochDay(), end2.toEpochDay()) -
      Math.max(start1.toEpochDay(), start2.toEpochDay());

    return overlap >= 0;
}

The LocalDate class provides two essential methods, isBefore() and isAfter(), for assessing the chronological relationship between LocalDate instances. We’ll utilize both methods to determine the non-overlap conditions:

boolean isOverlapUsingLocalDateAndCondition(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
    return !(end1.isBefore(start2) || start1.isAfter(end2));
}

Next, we’ll explore the use of LocalDate to find the minimum overlap between two date ranges:

boolean isOverlapUsingLocalDateAndFindMin(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
    long overlap1 = Math.min(end1.toEpochDay() - start1.toEpochDay(), 
      end1.toEpochDay() - start2.toEpochDay());
    long overlap2 = Math.min(end2.toEpochDay() - start2.toEpochDay(), 
      end2.toEpochDay() - start1.toEpochDay());

    return Math.min(overlap1, overlap2) >= 0;
}

Now, let’s set up test data using LocaleDate instances representing different date ranges.

First, let’s create the start date range:

LocalDate start1 = LocalDate.of(2024, 11, 15); 
LocalDate end1 = LocalDate.of(2024, 11, 20);

Next, let’s set the end date range to partially overlap:

LocalDate start1 = LocalDate.of(2024, 11, 15); 
LocalDate end1 = LocalDate.of(2024, 11, 20);

assertTrue(isOverlapUsingLocalDateAndDuration(start1, end1, start2, end2));
assertTrue(isOverlapUsingLocalDateAndCondition(start1, end1, start2, end2));
assertTrue(isOverlapUsingLocalDateAndFindMin(start1, end1, start2, end2));

We’ll follow this by setting the end date range to fully overlap:

LocalDate start1 = LocalDate.of(2024, 11, 16); 
LocalDate end1 = LocalDate.of(2024, 11, 18);

assertTrue(isOverlapUsingLocalDateAndDuration(start1, end1, start2, end2));
assertTrue(isOverlapUsingLocalDateAndCondition(start1, end1, start2, end2));
assertTrue(isOverlapUsingLocalDateAndFindMin(start1, end1, start2, end2));

Finally, when we set the end date range to consecutive ranges, we should expect no overlapping:

LocalDate start1 = LocalDate.of(2024, 11, 21); 
LocalDate end1 = LocalDate.of(2024, 11, 24);

assertFalse(isOverlapUsingLocalDateAndDuration(start1, end1, start2, end2)); 
assertFalse(isOverlapUsingLocalDateAndCondition(start1, end1, start2, end2)); 
assertFalse(isOverlapUsingLocalDateAndFindMin(start1, end1, start2, end2));

4.3. Using Joda-Time

Joda-Time, a widely adopted library for date and time operations in Java, simplifies complex temporal calculations and offers a convenient method called overlaps() to determine if two intervals overlap.

The overlaps() method takes two Interval objects as parameters and returns true if there is any intersection between the two intervals. In other words, it identifies whether there is any shared duration between the specified date ranges.

However, it is important to note that Joda-Time considers two intervals with the same start and end points as non-overlapping. This behavior is especially relevant when dealing with scenarios where precise boundaries matter and even a point in time is not considered an overlap.

Let’s see an implementation using Joda-Time:

boolean isOverlapUsingJodaTime(DateTime start1, DateTime end1, DateTime start2, DateTime end2) {
    Interval interval1 = new Interval(start1, end1);
    Interval interval2 = new Interval(start2, end2);

    return interval1.overlaps(interval2);
}

Now, let’s set up test data using Interval instances representing different date ranges. We begin with the partial overlapping:

DateTime startJT1 = new DateTime(2024, 12, 15, 0, 0);
DateTime endJT1 = new DateTime(2024, 12, 20, 0, 0);
DateTime startJT2 = new DateTime(2024, 12, 18, 0, 0);
DateTime endJT2 = new DateTime(2024, 12, 22, 0, 0);

assertTrue(isOverlapUsingJodaTime(startJT1, endJT1, startJT2, endJT2));

Let’s change the end date range to fully overlap:

DateTime startJT2 = new DateTime(2024, 12, 16, 0, 0);
DateTime endJT2 = new DateTime(2024, 12, 18, 0, 0);

assertTrue(isOverlapUsingJodaTime(startJT1, endJT1, startJT2, endJT2));

Finally, we change the end date range to a consecutive range, and again, it should return no overlapping:

DateTime startJT2 = new DateTime(2024, 12, 21, 0, 0);
DateTime endJT2 = new DateTime(2024, 12, 24, 0, 0);

assertFalse(isOverlapUsingJodaTime(startJT1, endJT1, startJT2, endJT2));

5. Conclusion

In this article, we explored various scenarios, mathematical formulas, and approaches to check if two date ranges overlap in Java. Understanding partial overlap, full overlap, consecutive ranges, and zero-range duration gave us a solid foundation for our exploration.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)