7

我有一组可能重叠的日期范围输入。我不想组合这些重叠的日期范围,而是想创建带有调整日期的新日期范围,例如:

|---------------------–|
        |-----| 
            |--------------–|

最终应该是:

|-------|---|-|--------|----|

有没有一种有效的方法可以用 Java 解决这个问题?

提前致谢!

更新: 我在第一个问题中没有提到我自己的方法,所以这里是:我只需获取间隔的开始日期和结束日期并将其添加到排序集中。之后,我将遍历该集合并根据重新排序的日期创建新的间隔。

4

5 回答 5

5

基本思想:

  • 将每个区间拆分为起点和终点
  • 对点进行排序
  • 遍历这些点并在所有相邻点之间创建新的间隔。
    跟踪,startIntervals - endIntervals只要此数字为 0,则该范围内不应有间隔。
于 2013-07-09T08:13:30.903 回答
5

您可以使用Guava 的 Range支持。没有将它与 Date 对象一起使用,但它可以工作。结合RangeSet,您可以添加所有日期范围,然后检查日期是否在范围内,获取完整范围等。

于 2013-07-09T08:10:23.547 回答
4

要解决此类问题,请使用开始日期作为第一个条件,结束日期作为第二个条件对间隔进行排序。这样,您可以在单次迭代中使间隔相交。如果您的区间与另一个刚开始的区间重叠,那么它在排序顺序中的继任者应该是重叠区间,依此类推。

于 2013-07-09T08:09:00.953 回答
1
于 2017-03-06T04:39:29.150 回答
1

使用我的时间库Time4J,可以使用以下方便的解决方案,而无需对实际实现进行太多头脑风暴:

// create the intervals
SimpleInterval<Date> i1 = SimpleInterval.between(new Date(0L), new Date(5000L));
SimpleInterval<Date> i2 = SimpleInterval.between(new Date(0L), new Date(7000L));
SimpleInterval<Date> i3 = SimpleInterval.between(new Date(1000L), new Date(2000L));

// collect the intervals
IntervalCollection<Date> icoll =
    IntervalCollection.onTraditionalTimeLine().plus(i3).plus(i2).plus(i1);

// split and iterate
for (ChronoInterval<Date> interval : icoll.withSplits().getIntervals()) {
    System.out.println(interval);
}

输出:

[Thu Jan 01 01:00:00 CET 1970/Thu Jan 01 01:00:01 CET 1970)
[Thu Jan 01 01:00:01 CET 1970/Thu Jan 01 01:00:02 CET 1970)
[Thu Jan 01 01:00:02 CET 1970/Thu Jan 01 01:00:05 CET 1970)
[Thu Jan 01 01:00:05 CET 1970/Thu Jan 01 01:00:07 CET 1970)

定义和收集所有区间后的主要调整只是在区间集合上调用withSplits() 。

另一个优点是可以稍微调整代码,以便使用其他类型,如java.time.InstantJava-8 中的类或内置的 Time4J 类型,如Moment,等PlainDatePlainTimestamp也很容易实现。

于 2017-03-07T16:55:25.470 回答