2017-06-28 13 views
1

私は、オーバーラップしてギャップを含むことができる一連の[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でこれを行う方法上の任意のアイデア?

+0

java8を使用する場合は、java.time.Periodを使用できます。次に、すべての期間をソートし、2つの連続期間の開始/終了を比較します。 – Heri

+0

@Heriいいえ、「期間」は開始日も終了日もありません(日付行に固定されていません)。 OPには間隔の解決策が必要です。 –

+0

期間は、問題を解決するために使用できる多くの操作を提供します。between()は、2つのLocalDateを使用して構築します。 addTo()とsubtractFrom()を使用すると、計算を行うことができます – Heri

答えて

1

あなたは私のライブラリTime4Jrange-packageを試してみて、このコードを使用する可能性があります:あなたの期待される結果について

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]"のような区間は、1日だけで構成されます(期待区間リストの最初のエントリにも表示されています)。

ただし、「[2011-01-01/2011-01-01]」の間隔は予期していないようですが、この日付(1日のみの間隔)は間隔Eの重複領域です+ Fと期待される間隔のリストにも表示する必要があります。Javaの-8との相互運用性について

また、種類net.time4j.PlainDatejava.time.LocalDatetoTemporalAccessor()またはfrom(LocalDate)のようなダイレクトコンバージョン方式を適用することができます。

+0

はい、これはまさに私の意図です。そして、はい、あなたは失われた間隔について正しいです。 :) – Bossk

+1

上記のtoString()によって生成された角括弧は、閉じた間隔の境界を表します(日付間隔の標準)。とにかく、独自のカスタマイズされた間隔形式を選択することもできます。[print](http://time4j.net/javadoc-en/net/time4j/range/IsoInterval.html#print-net.time4j)などのAPIメソッドを参照してください。 format.expert.ChronoPrinter-java.lang.String-)。 –

0

まず、それらすべてを並べ替えます。開始日によって

そして、それらを反復処理し、次で、各比較に次のすべて:

  • curr.end >= next.start場合、curr.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) 
関連する問題