问题
I'm using Joda-Time library in Java to keep track a list of time intervals. I want to check if a list of Interval objects fully covers every minute of a month. There's about 30 intervals of varying length from a few hours to a few days.
I thought a cheap way to do this is to sort the list of intervals by start time, then successively check if there is a break between the intervals within the range of the month. If yes, then the month is not fully covered.
I'm stuck on the first part, sorting the list. I planned to use Arrays.sort(), but it needs the elements to implement the comparable interface. However, after looking through the source, Joda-Time's Interval class doesn't seem to have one I can override, and I can't extend it to write my own compareTo method.
Other than writing my own sorting method, anyone know an easier way to accomplish this? Thanks
回答1:
You can use next method
static boolean covers(Interval month, List<Interval> intervals)
{
//assumes intervals are sorted already on start times
final MutableInterval monthInterval = new MutableInterval(month);
start: for (final Interval interval : intervals)
{
if (interval.getStartMillis() <= monthInterval.getStartMillis()
&& interval.getEndMillis() > monthInterval.getStartMillis())
{
if (interval.getEndMillis() > monthInterval.getEndMillis())
{
return true;
}
monthInterval.setStartMillis(interval.getEndMillis());
// continue start; // loop continues regardless
} else {
if (interval.overlaps(month)) return false;
}
}
return monthInterval.getStartMillis()== monthInterval.getEndMillis();
}
Example
static final List<Interval> intervals = new ArrayList<Interval>();
static
{
intervals.add(new Interval(new DateTime(1990, 05, 15, 00, 00, 00, 00), new DateTime(1990, 05, 18, 00, 00, 00, 00)));
intervals.add(new Interval(new DateTime(1990, 04, 28, 00, 00, 00, 00), new DateTime(1990, 05, 18, 00, 00, 00, 00)));
intervals.add(new Interval(new DateTime(1990, 05, 17, 00, 00, 00, 00), new DateTime(1990, 05, 21, 00, 00, 00, 00)));
intervals.add(new Interval(new DateTime(1990, 05, 21, 00, 00, 00, 00), new DateTime(1990, 05, 29, 00, 00, 00, 00)));
intervals.add(new Interval(new DateTime(1990, 05, 22, 00, 00, 00, 00), new DateTime(1990, 05, 25, 00, 00, 00, 00)));
intervals.add(new Interval(new DateTime(1990, 05, 27, 00, 00, 00, 00), new DateTime(1990, 06, 02, 00, 00, 00, 00)));
}
public static void main(String[] args)
{
final DateTime startOfMonth = new DateTime(1990, 05, 01, 00, 00);
final Interval monthInterval = new Interval(startOfMonth, startOfMonth.plusMonths(1));
covers(monthInterval, intervals);
}
static boolean covers(Interval month, List<Interval> intervals)
{
final MutableInterval monthInterval = new MutableInterval(month);
start: for (final Interval interval : intervals)
{
if (interval.getStartMillis() <= monthInterval.getStartMillis()
&& interval.getEndMillis() > monthInterval.getStartMillis())
{
if (interval.getEndMillis() > monthInterval.getStartMillis())
{
return true;
}
monthInterval.setStartMillis(interval.getEndMillis());
continue start;
}
}
return monthInterval.getStartMillis()== monthInterval.getEndMillis();
}
回答2:
You can use Collections#sort with a Comparator to sort the time intervals and use Interval#gap to check for gaps. The following code returns true if the interval between start and end is fully covered by the timeIntervals:
public static boolean isCovered(List<Interval> timeIntervals, DateTime start, DateTime end) {
if (timeIntervals.isEmpty()) {
return false;
}
// create sorted set from original List to get
// sorted intervals without double entries
Set<Interval> intervalSet = new TreeSet<>(new Comparator<Interval>() {
@Override
public int compare(Interval o1, Interval o2) {
return o1.getStart().compareTo(o2.getStart());
}
});
intervalSet.addAll(timeIntervals);
List<Interval> intervals = new ArrayList<>(intervalSet);
// remove intervals completely contained in others
List<Interval> removedIntervals = new ArrayList<>();
for (int i = 0; i < (intervals.size()-1); i++) {
for (int j = (i+1); j < intervals.size(); j++) {
if (intervals.get(i).contains(intervals.get(j))) {
if (!removedIntervals.contains(intervals.get(j))) {
removedIntervals.add(intervals.get(j));
}
}
}
}
intervals.removeAll(removedIntervals);
if (intervals.get(0).getStart().isAfter(start) ||
intervals.get(intervals.size() - 1).getEnd().isBefore(end)) {
return false;
}
// check for gaps
for (int i = 0; i < (intervals.size() - 1); i++) {
Interval gap = intervals.get(i).gap(intervals.get(i+1));
if (gap != null && new Interval(start, end).overlaps(gap)) {
// gap detected between interval i and interval (i+1)
return false;
}
}
return true;
}
来源:https://stackoverflow.com/questions/20679957/how-to-check-if-a-list-of-intervals-joda-time-fully-covers-a-month-in-java