1

So I have this function I created called isDateOverlapping. It takes in (of all type LocalDate):

  • Start Date 1
  • End Date 1
  • Start Date 2
  • End Date 2

What this function does is it tells me if the 2 date periods are overlapping or not.

For example if I have 1 period from 2019-06-15 to 2019-06-18 and another period from 2019-06-15 to 2019-06-12. It would return true because the 2 date periods overlap.

However my function doesn't seem to always return the right answer. Could you please help.

public boolean isDateOverlapping(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {

    if (start1.isAfter(start2) && start2.isBefore(start1)) {
        return true;

    } else if (end1.isBefore(end2) && start1.isAfter(start2)) {
        return true;
    } else if (start1.isAfter(end1) && end2.isBefore(start2)) {
        return true;
    }

    return false;

}
Joey Yue
  • 29
  • 1
  • 4
  • 1
    Do you consider a period overlapping another one if the last day of the earlier period is exactly the first date of the later one? That is kind of an edge case that should be defined before implementing anything. – deHaar Jun 24 '19 at 08:55
  • *another period from 2019-06-15 to 2019-06-12* — so a period can go backward? Do you want this treated the same as a period from 2019-06-12 to 2019-06-15? – Ole V.V. Jun 24 '19 at 18:31
  • 1
    For special edge cases like empty intervals etc. see also my [post](https://stackoverflow.com/a/43315879/2491410) – Meno Hochschild Jun 25 '19 at 04:03

2 Answers2

8

The easiest way to understand this is two consider the 4 possibilities:

  1. the second interval contains the first interval: s2 < s1 < e1 < e2
  2. The second interval contains the start of the first interval: s2 < s1 < e2 < e1
  3. The second interval contains the end of the first interval: s1 < s2 < e1 < e2
  4. The second interval is contained in the first interval: s1 < s2 < e2 < e1

They can be illustrated as follows:

        1.                  2.                    3.               4.

|---------------|       |-------|                |------|        |----|     Second Interval
     |-----|                 |------|        |-------|       |-----------|  First Interval
s2   s1    e1   e2      s2   s1 e2  e1      s1  s2   e1 e2   s1  s2  e2  e1

The common invariant in all of these 4 cases is that the second interval must start before the first interval ends, and the second interval must end after the first interval begins.

This gives you:

public boolean isDateOverlapping(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
    return start2.isBefore(end1) && end2.isAfter(start1); 
}

Note that you might require a small change if you want your method to return true when the intervals overlap at a single point. In that case, you need to replace start2.isBefore(end1) with !start2.isAfter(end1) and end2.isAfter(start1) with !end2.isBefore(start1).

Also note that I'm assuming start1 <= end1 and start2 <= end2. If that's not always the case, you'll have to check that too, and swap startN with endN, if necessary, before checking the above conditions.

Eran
  • 387,369
  • 54
  • 702
  • 768
2

To determine if two date period overlapping only below logic sufficient.

(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)

Diptesh
  • 46
  • 4