如果我的理解正确:您正在尝试找出所有“可用”的时间段,当有一些“类似缺席”的时间段列表时。
那么,当有许多“类似缺席”的时间段列表时,有一个完整的解决方案可以解决问题:
public class Extra_1_interval_merge {
@Test
public void testAvailablePeriod() {
List<MyPeriod> absentPeriods0 = new ArrayList<>();
absentPeriods0.add(makePeriod(LocalDate.now(), LocalDate.now().plusDays(1), PeriodType.ABSENT));
absentPeriods0.add(makePeriod(LocalDate.now().plusDays(4), LocalDate.now().plusDays(6), PeriodType.ABSENT));
absentPeriods0.add(makePeriod(LocalDate.now().plusDays(2), LocalDate.now().plusDays(3), PeriodType.ABSENT));
List<MyPeriod> absentPeriods1 = new ArrayList<>();
absentPeriods1.add(makePeriod(LocalDate.now(), LocalDate.now().plusDays(2), PeriodType.UNAVAILABLE));
absentPeriods1.add(makePeriod(LocalDate.now().plusDays(5), LocalDate.now().plusDays(7), PeriodType.UNAVAILABLE));
List<List<MyPeriod>> absentListList = new ArrayList<>();
absentListList.add(absentPeriods0);
absentListList.add(absentPeriods1);
System.out.println(getAvailablePeriods(absentListList));
}
private List<MyPeriod> getAvailablePeriods(List<List<MyPeriod>> absentListList) {
List<MyPeriod> tempList = new ArrayList<>();
absentListList.stream().forEach(list -> tempList.addAll(list));
List<MyPeriod> absentList = tempList.stream().sorted((period1, period2) -> {
if (!period1.startDate.isEqual(period2.startDate)) {
return period1.startDate.compareTo(period2.startDate);
} else {
return period1.endDate.compareTo(period2.endDate);
}
}).collect(toList());
List<MyPeriod> mergedPeriods = new ArrayList<>();
for (MyPeriod period : absentList) {
if (mergedPeriods.isEmpty()) {
mergedPeriods.add(period);
} else {
MyPeriod lastPeriod = mergedPeriods.get(mergedPeriods.size() - 1);
if (!lastPeriod.endDate.isBefore(period.startDate)) {
if (lastPeriod.endDate.isBefore(period.endDate)) {
lastPeriod.endDate = period.endDate;
}
} else {
mergedPeriods.add(period);
}
}
}
List<MyPeriod> availablePeriods = new ArrayList<>();
for (int i = 0, len = mergedPeriods.size(); i < len - 1; i++) {
availablePeriods.add(makePeriod(mergedPeriods.get(i).endDate, mergedPeriods.get(i + 1).startDate, PeriodType.AVAILABLE));
}
return availablePeriods;
}
private MyPeriod makePeriod(LocalDate startDate, LocalDate endDate, PeriodType periodType) {
MyPeriod thePeriod = null;
switch (periodType) {
case ABSENT:
thePeriod = new AbsentPeriod();
break;
case UNAVAILABLE:
thePeriod = new UnavailablePeriod();
break;
case AVAILABLE:
thePeriod = new AvailablePeriod();
break;
default:
thePeriod = new MyPeriod();
break;
}
thePeriod.startDate = startDate;
thePeriod.endDate = endDate;
return thePeriod;
}
enum PeriodType {
ABSENT,
UNAVAILABLE,
AVAILABLE;
}
class MyPeriod {
LocalDate startDate;
LocalDate endDate;
@Override
public String toString() {
return String.format("Start: %s, End: %s", startDate, endDate);
}
}
class AbsentPeriod extends MyPeriod {
}
class UnavailablePeriod extends MyPeriod {
}
class AvailablePeriod extends MyPeriod {
}
}
对于输入:
- 缺席期列表-1:[0,1],[4,6],[2,3]
- 缺席期列表-2:[0,2],[5,7]
最终结果将为:
如果需要,您可以尝试更多的缺席期列表。
更新
我不知道为什么OP在这里需要三种不同类型的Period/Interval
。但是为了解决具体问题,我根据OP的需求更新了解决方案。
正如其他评论所指出的那样,为什么要有三种不同的类型?我毫无头绪……