所以我创建了这个名为 isDateOverlapping
的函数。它接收(所有类型的 LocalDate
):
- 开始日期 1
- 结束日期 1
- 开始日期 2
- 结束日期 2
这个函数的作用是告诉我两个日期周期是否重叠。
例如,如果我有 1 个时间段从 2019-06-15 到 2019-06-18
和另一个时间段从 2019-06-15 到 2019-06-12
。它会返回 true,因为 2 个日期周期重叠。
但是我的函数似乎并不总是返回正确的答案。你能帮忙吗?
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;
}
理解这一点的最简单方法是考虑 4 种可能性:
- 第二个区间包含第一个区间:s2 < s1 < e1 < e2
- 第二个间隔包含第一个间隔的开始:s2 < s1 < e2 < e1
- 第二个区间包含第一个区间的结尾:s1 < s2 < e1 < e2
- 第二个区间包含在第一个区间中:s1 < s2 < e2 < e1
它们可以表示如下:
1. 2. 3. 4.
|---------------| |-------| |------| |----| Second Interval
|-----| |------| |-------| |-----------| First Interval
s2 s1 e1 e2 s2 s1 e2 e1 s1 s2 e1 e2 s1 s2 e2 e1
所有这 4 种情况的共同不变性是,第二个间隔必须在第一个间隔结束之前开始,而第二个间隔必须在第一个间隔开始之后结束。
这给你:
public boolean isDateOverlapping(LocalDate start1, LocalDate end1, LocalDate start2, LocalDate end2) {
return start2.isBefore(end1) && end2.isAfter(start1);
}
请注意,如果您希望方法在间隔在单个点重叠时返回 true,则可能需要进行小的更改。在这种情况下,您需要替换 start2.isBefore(end1)
与 !start2.isAfter(end1)
和 end2.isAfter(start1)
与 !end2.isBefore(start1)
.
另请注意,我假设 start1 <= end1
和 start2 <= end2
.如果情况并非总是如此,您也必须检查它,并在检查上述条件之前根据需要交换 startN 和 endN。