拆分重叠并添加缺失的间隔

时间:2017-06-28 19:44:08

标签: java intervals

我有一组[startdate,enddate]间隔,它们可以重叠并包含间隙。 我的目标是建立一个连续的新间隔列表,没有间隙,没有任何重叠日期。

范围示例:

[-----------------------------------A-----------------------]
[-B]
   [-C]
      [D]
                  [-----E-----]
                              [-----F----]
                                                                    [-----G-----]                

A [2009-01-01 - 2014-01-01]     ~5 years
B [2009-01-01 - 2009-01-02]     2 days
C [2009-01-02 - 2009-01-03]     2 days
D [2009-01-04 - 2009-01-04]     1 day
E [2010-01-01 - 2011-01-01]     ~1 year
F [2011-01-01 - 2012-01-01]     ~1 year, a gap after this interval
G [2015-01-01 - 2016-01-01]     ~1 year

我期望的是这个新的间隔列表:

[2009-01-01 - 2009-01-01]
[2009-01-02 - 2009-01-02]
[2009-01-03 - 2009-01-03]
[2009-01-04 - 2009-01-04]
[2009-01-05 - 2009-12-31]
[2010-01-01 - 2010-12-31]
[2011-01-01 - 2012-01-01]
[2012-01-02 - 2014-01-01]
[2014-01-02 - 2014-12-31]
[2015-01-01 - 2016-01-01]

因此,对于差距,添加了新的间隔。具有相同开始日期和结束日期的间隔完全有效,应按原样处理。

即使在以有效的方式实现这一目标之前,我仍然坚持实现这一目标的最佳方式:(

有关如何在Java中执行此操作的任何想法?

2 个答案:

答案 0 :(得分:2)

您可以尝试我的库range-packageTime4J并使用此代码:

DateInterval a = DateInterval.between(PlainDate.of(2009, 1, 1), PlainDate.of(2014, 1, 1));
DateInterval b = DateInterval.between(PlainDate.of(2009, 1, 1), PlainDate.of(2009, 1, 2));
DateInterval c = DateInterval.between(PlainDate.of(2009, 1, 2), PlainDate.of(2009, 1, 3));
DateInterval d = DateInterval.between(PlainDate.of(2009, 1, 4), PlainDate.of(2009, 1, 4));
DateInterval e = DateInterval.between(PlainDate.of(2010, 1, 1), PlainDate.of(2011, 1, 1));
DateInterval f = DateInterval.between(PlainDate.of(2011, 1, 1), PlainDate.of(2012, 1, 1));
DateInterval g = DateInterval.between(PlainDate.of(2015, 1, 1), PlainDate.of(2016, 1, 1));

List<DateInterval> intervals = Arrays.asList(a, b, c, d, e, f, g);

IntervalCollection<PlainDate> icoll = IntervalCollection.onDateAxis().plus(intervals);

for (ChronoInterval<PlainDate> gap : icoll.withGaps().getIntervals()) {
    icoll = icoll.plus(gap);
}

System.out.println(icoll.withSplits());

[2009-01-01/2009-01-01],
[2009-01-02/2009-01-02],
[2009-01-03/2009-01-03],
[2009-01-04/2009-01-04],
[2009-01-05/2009-12-31],
[2010-01-01/2010-12-31],
[2011-01-01/2011-01-01],
[2011-01-02/2012-01-01],
[2012-01-02/2014-01-01],
[2014-01-02/2014-12-31],
[2015-01-01/2016-01-01]

备注您的预期结果:

您的陈述

  

我的目标是建立一个连续的新间隔列表,没有间隙   没有任何重叠日期。

通过上面的代码实现。在分割之前,间隙作为正常间隔添加到整个间隔集合。默认情况下,Time4J中的所有日期间隔都作为封闭间隔处理(可配置)。这意味着,例如“[2009-01-01 / 2009-01-01]”之类的时间间隔仅包含一天(正如您在预期时间间隔列表的第一个条目中所示)。

但是,您似乎没有期望间隔“[2011-01-01 / 2011-01-01]”,但只是这个日期(仅包含一天的间隔)是间隔E +之间的重叠区域F也应出现在预期的间隔列表中。

关于与Java-8的互操作性:

您还可以在net.time4j.PlainDatejava.time.LocalDate类型之间应用toTemporalAccessor()from(LocalDate)等直接转化方法。

答案 1 :(得分:0)

首先,按开始日期对它们进行排序。

然后迭代它们,并将以下所有内容与下一个进行比较:

  • 如果curr.end >= next.startcurr.end = next.start - 1

  • 如果curr.end < curr.start然后将其删除

  • 如果curr.end < next.start - 1然后添加新的:

    new.start = curr.end + 1
    new.end = next.start - 1
    

同时跟踪最大结束日期(更新前),如果max(end) > last.end,则添加新日期:

new.start = last.end + 1
new.end = max(end)