fix JodaUtils.condenseIntervals(..) to correctly take end or current/next interval on overlap (#3793)

* remove unused duplicate JodaUtils.java

* fix JodaUtils.condenseIntervals(..) to correctly take end or current/next interval on overlap
This commit is contained in:
Himanshu 2016-12-20 14:07:23 -06:00 committed by Gian Merlino
parent fd14997b1d
commit c5df30d813
4 changed files with 16 additions and 268 deletions

View File

@ -23,9 +23,7 @@ import com.google.common.base.Predicate;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Lists; import com.google.common.collect.Lists;
import com.google.common.collect.Sets; import com.google.common.collect.Sets;
import io.druid.java.util.common.guava.Comparators; import io.druid.java.util.common.guava.Comparators;
import org.joda.time.DateTime; import org.joda.time.DateTime;
import org.joda.time.Interval; import org.joda.time.Interval;
@ -60,8 +58,15 @@ public class JodaUtils
while (intervalsIter.hasNext()) { while (intervalsIter.hasNext()) {
Interval next = intervalsIter.next(); Interval next = intervalsIter.next();
if (currInterval.overlaps(next) || currInterval.abuts(next)) { if (currInterval.abuts(next)) {
currInterval = new Interval(currInterval.getStart(), next.getEnd()); currInterval = new Interval(currInterval.getStart(), next.getEnd());
} else if(currInterval.overlaps(next)) {
DateTime nextEnd = next.getEnd();
DateTime currEnd = currInterval.getEnd();
currInterval = new Interval(
currInterval.getStart(),
nextEnd.isAfter(currEnd) ? nextEnd : currEnd
);
} else { } else {
retVal.add(currInterval); retVal.add(currInterval);
currInterval = next; currInterval = next;

View File

@ -104,7 +104,11 @@ public class JodaUtilsTest
new Interval("2011-02-03/2011-02-08"), new Interval("2011-02-03/2011-02-08"),
new Interval("2011-03-01/2011-03-02"), new Interval("2011-03-01/2011-03-02"),
new Interval("2011-03-03/2011-03-04"), new Interval("2011-03-03/2011-03-04"),
new Interval("2011-03-05/2011-03-06") new Interval("2011-03-05/2011-03-06"),
new Interval("2011-04-01/2011-04-05"),
new Interval("2011-04-02/2011-04-03"),
new Interval("2011-05-01/2011-05-05"),
new Interval("2011-05-02/2011-05-07")
); );
for (int i = 0; i < 20; ++i) { for (int i = 0; i < 20; ++i) {
@ -115,7 +119,9 @@ public class JodaUtilsTest
new Interval("2011-02-01/2011-02-08"), new Interval("2011-02-01/2011-02-08"),
new Interval("2011-03-01/2011-03-02"), new Interval("2011-03-01/2011-03-02"),
new Interval("2011-03-03/2011-03-04"), new Interval("2011-03-03/2011-03-04"),
new Interval("2011-03-05/2011-03-06") new Interval("2011-03-05/2011-03-06"),
new Interval("2011-04-01/2011-04-05"),
new Interval("2011-05-01/2011-05-07")
), ),
JodaUtils.condenseIntervals(intervals) JodaUtils.condenseIntervals(intervals)
); );

View File

@ -1,141 +0,0 @@
/*
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Metamarkets licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.druid.java.util.common;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import io.druid.java.util.common.guava.Comparators;
import org.joda.time.DateTime;
import org.joda.time.Interval;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.TreeSet;
/**
*/
public class JodaUtils
{
public static ArrayList<Interval> condenseIntervals(Iterable<Interval> intervals)
{
ArrayList<Interval> retVal = Lists.newArrayList();
TreeSet<Interval> sortedIntervals = Sets.newTreeSet(Comparators.intervalsByStartThenEnd());
for (Interval interval : intervals) {
sortedIntervals.add(interval);
}
if (sortedIntervals.isEmpty()) {
return Lists.newArrayList();
}
Iterator<Interval> intervalsIter = sortedIntervals.iterator();
Interval currInterval = intervalsIter.next();
while (intervalsIter.hasNext()) {
Interval next = intervalsIter.next();
if (currInterval.overlaps(next) || currInterval.abuts(next)) {
currInterval = new Interval(currInterval.getStart(), next.getEnd());
} else {
retVal.add(currInterval);
currInterval = next;
}
}
retVal.add(currInterval);
return retVal;
}
public static Interval umbrellaInterval(Iterable<Interval> intervals)
{
ArrayList<DateTime> startDates = Lists.newArrayList();
ArrayList<DateTime> endDates = Lists.newArrayList();
for (Interval interval : intervals) {
startDates.add(interval.getStart());
endDates.add(interval.getEnd());
}
DateTime minStart = minDateTime(startDates.toArray(new DateTime[]{}));
DateTime maxEnd = maxDateTime(endDates.toArray(new DateTime[]{}));
if (minStart == null || maxEnd == null) {
throw new IllegalArgumentException("Empty list of intervals");
}
return new Interval(minStart, maxEnd);
}
public static boolean overlaps(final Interval i, Iterable<Interval> intervals)
{
return Iterables.any(
intervals, new Predicate<Interval>()
{
@Override
public boolean apply(Interval input)
{
return input.overlaps(i);
}
}
);
}
public static DateTime minDateTime(DateTime... times)
{
if (times == null) {
return null;
}
switch (times.length) {
case 0:
return null;
case 1:
return times[0];
default:
DateTime min = times[0];
for (int i = 1; i < times.length; ++i) {
min = min.isBefore(times[i]) ? min : times[i];
}
return min;
}
}
public static DateTime maxDateTime(DateTime... times)
{
if (times == null) {
return null;
}
switch (times.length) {
case 0:
return null;
case 1:
return times[0];
default:
DateTime max = times[0];
for (int i = 1; i < times.length; ++i) {
max = max.isAfter(times[i]) ? max : times[i];
}
return max;
}
}
}

View File

@ -1,122 +0,0 @@
/*
* Licensed to Metamarkets Group Inc. (Metamarkets) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Metamarkets licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package io.druid.java.util.common;
import org.joda.time.Interval;
import org.junit.Assert;
import org.junit.Test;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
*/
public class JodaUtilsTest
{
@Test
public void testUmbrellaIntervalsSimple() throws Exception
{
List<Interval> intervals = Arrays.asList(
new Interval("2011-03-03/2011-03-04"),
new Interval("2011-01-01/2011-01-02"),
new Interval("2011-02-01/2011-02-05"),
new Interval("2011-02-03/2011-02-08"),
new Interval("2011-01-01/2011-01-03"),
new Interval("2011-03-01/2011-03-02"),
new Interval("2011-03-05/2011-03-06"),
new Interval("2011-02-01/2011-02-02")
);
Assert.assertEquals(
new Interval("2011-01-01/2011-03-06"),
JodaUtils.umbrellaInterval(intervals)
);
}
@Test
public void testUmbrellaIntervalsNull() throws Exception
{
List<Interval> intervals = Arrays.asList();
Throwable thrown = null;
try {
Interval res = JodaUtils.umbrellaInterval(intervals);
}
catch (IllegalArgumentException e) {
thrown = e;
}
Assert.assertNotNull("Empty list of intervals", thrown);
}
@Test
public void testCondenseIntervalsSimple() throws Exception
{
List<Interval> intervals = Arrays.asList(
new Interval("2011-01-01/2011-01-02"),
new Interval("2011-01-02/2011-01-03"),
new Interval("2011-02-01/2011-02-05"),
new Interval("2011-02-01/2011-02-02"),
new Interval("2011-02-03/2011-02-08"),
new Interval("2011-03-01/2011-03-02"),
new Interval("2011-03-03/2011-03-04"),
new Interval("2011-03-05/2011-03-06")
);
Assert.assertEquals(
Arrays.asList(
new Interval("2011-01-01/2011-01-03"),
new Interval("2011-02-01/2011-02-08"),
new Interval("2011-03-01/2011-03-02"),
new Interval("2011-03-03/2011-03-04"),
new Interval("2011-03-05/2011-03-06")
),
JodaUtils.condenseIntervals(intervals)
);
}
@Test
public void testCondenseIntervalsMixedUp() throws Exception
{
List<Interval> intervals = Arrays.asList(
new Interval("2011-01-01/2011-01-02"),
new Interval("2011-01-02/2011-01-03"),
new Interval("2011-02-01/2011-02-05"),
new Interval("2011-02-01/2011-02-02"),
new Interval("2011-02-03/2011-02-08"),
new Interval("2011-03-01/2011-03-02"),
new Interval("2011-03-03/2011-03-04"),
new Interval("2011-03-05/2011-03-06")
);
for (int i = 0; i < 20; ++i) {
Collections.shuffle(intervals);
Assert.assertEquals(
Arrays.asList(
new Interval("2011-01-01/2011-01-03"),
new Interval("2011-02-01/2011-02-08"),
new Interval("2011-03-01/2011-03-02"),
new Interval("2011-03-03/2011-03-04"),
new Interval("2011-03-05/2011-03-06")
),
JodaUtils.condenseIntervals(intervals)
);
}
}
}