给定两个日期范围列表,如何在java中查找不重叠的日期

给定两个日期范围列表,如何在java中查找不重叠的日期,java,date,datetime,overlap,Java,Date,Datetime,Overlap,我不确定我的标题是否正确,但这正是我努力实现的目标。 考虑下面两个班,缺席期,无效期。< /P> class AbsentPeriod { Date startDate; Date endDate; } class UnavailablePeriod { Date startDate; Date endDate; } 给定 Date StartDate // starting point Date EndDate //ending point List<

我不确定我的标题是否正确,但这正是我努力实现的目标。 考虑下面两个班,缺席期,无效期。< /P>
class AbsentPeriod
{
    Date startDate;
    Date endDate;
}

class UnavailablePeriod
{
    Date startDate;
    Date endDate;
}
给定

Date StartDate // starting point
Date EndDate //ending point
List<AbsentPeriod> absentperiods
List<UnavailablePeriods> unavailablePeriods

您可以使用下面的函数遍历
AbsentPeriod
UnavailablePeriod
的列表,检查日期是否重叠,如果不重叠,则将其添加到结果列表中:

public static boolean dateRangeOverlap(Date givenStartDate, Date givenEndDate, Date listItemStartDate, Date listItemEndDate)
{
    boolean result = false;
    if (givenStartDate !=null && givenEndDate !=null && listItemStartDate !=null && listItemEndDate != null){
        result = (givenStartDate.getTime() <= listItemEndDate.getTime()) && (givenEndDate.getTime() >= listItemStartDate.getTime()); 
    }
    return result;
}
public静态布尔dateRangeOverlap(日期givenStarDate、日期givenEndDate、日期listItemStartDate、日期listItemEndDate)
{
布尔结果=假;
如果(givenStartDate!=null&&givenEndDate!=null&&listItemStartDate!=null&&listItemEndDate!=null){
结果=(givenStartDate.getTime()=listItemStartDate.getTime());
}
返回结果;
}

如果我的理解是正确的:您试图找出所有可用的时段,但有一些缺席,如时段列表

然后,当有大量的缺少时,有一个完整的解决方案,如时段列表:

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) {
        // Step - 1: Collect all periods;
        List<MyPeriod> tempList = new ArrayList<>();
        absentListList.stream().forEach(list -> tempList.addAll(list));

        // Step - 2: Sort the periods based on the startDate and then endDate;
        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());

        // Step - 3: Merge all overlapped periods to form an one-dimension occupied period list;
        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);
                }
            }
        }

        // Step - 4: Pick the periods from the occupied period list;
        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 {
    }

}
公共类额外\u 1\u间隔\u合并{
@试验
公共无效测试有效期(){
List absentPeriods0=newarraylist();
add(makePeriod(LocalDate.now(),LocalDate.now().plusDays(1),PeriodType.缺席));
add(makePeriod(LocalDate.now().plusDays(4),LocalDate.now().plusDays(6),PeriodType.缺席));
add(makePeriod(LocalDate.now().plusDays(2),LocalDate.now().plusDays(3),PeriodType.缺席));
List absentPeriods1=new ArrayList();
添加(makePeriod(LocalDate.now(),LocalDate.now().plusDays(2),PeriodType.UNAVAILABLE));
添加(makePeriod(LocalDate.now().plusDays(5),LocalDate.now().plusDays(7),PeriodType.UNAVAILABLE));
List absentListList=new ArrayList();
absentListList.add(absentPeriods0);
添加(absentPeriods1);
System.out.println(getAvailablePeriods(absentListList));
}
私有列表getAvailablePeriods(列表缺席列表列表){
//步骤1:收集所有期间;
List templast=new ArrayList();
absentListList.stream().forEach(list->templast.addAll(list));
//步骤2:根据开始日期和结束日期对时段进行排序;
List-absentList=templast.stream().sorted((period1,period2)->{
如果(!period1.startDate.isEqual(period2.startDate)){
返回周期1.startDate.compareTo(周期2.startDate);
}否则{
返回周期1.endDate.compareTo(周期2.endDate);
}
}).collect(toList());
//步骤-3:合并所有重叠的期间,形成一维占用期间列表;
List mergedPeriods=new ArrayList();
对于(我的期间:缺席列表){
if(mergedPeriods.isEmpty()){
合并期间。添加(期间);
}否则{
MyPeriod lastPeriod=mergedPeriods.get(mergedPeriods.size()-1);
如果(!lastPeriod.endDate.isBefore(period.startDate)){
if(lastPeriod.endDate.isBefore(period.endDate)){
lastPeriod.endDate=period.endDate;
}
}否则{
合并期间。添加(期间);
}
}
}
//步骤-4:从占用期间列表中选择期间;
List availablePeriods=new ArrayList();
for(int i=0,len=mergedPeriods.size();i
对于输入:

  • 缺席期间列表-1:[0,1],[4,6],[2,3]
  • 缺勤期间列表-2:[0,2],[5,7]
最终结果将是:

  • 有效期列表:[3,4]
如果需要,您可以尝试更多缺勤时间列表

更新 我不知道为什么OP在这里需要三种不同类型的
时段/间隔。但为了解决具体问题,我根据OP的需要更新了解决方案


正如其他评论所指出的,为什么有三种不同的类型?我不知道…

到目前为止您尝试了什么?虽然它使用了JodaTime,但它应该可以轻松地转换为Java日期/时间API,“句点”是句点,句点(对不起)-而在您的示例中,它添加了一些可能的说明,尽量避免创建表示相同概念但因特定目的而命名的数据类型,这就是为什么要使用变量名;)-我可能会尝试使用
Range
Span
作为“pe”
public static boolean dateRangeOverlap(Date givenStartDate, Date givenEndDate, Date listItemStartDate, Date listItemEndDate)
{
    boolean result = false;
    if (givenStartDate !=null && givenEndDate !=null && listItemStartDate !=null && listItemEndDate != null){
        result = (givenStartDate.getTime() <= listItemEndDate.getTime()) && (givenEndDate.getTime() >= listItemStartDate.getTime()); 
    }
    return result;
}
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) {
        // Step - 1: Collect all periods;
        List<MyPeriod> tempList = new ArrayList<>();
        absentListList.stream().forEach(list -> tempList.addAll(list));

        // Step - 2: Sort the periods based on the startDate and then endDate;
        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());

        // Step - 3: Merge all overlapped periods to form an one-dimension occupied period list;
        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);
                }
            }
        }

        // Step - 4: Pick the periods from the occupied period list;
        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 {
    }

}