我正在使用Java中的Joda-Time库来跟踪时间间隔列表。我想检查间隔对象列表是否完全覆盖一个月的每一分钟。大约有 30 个不同长度的间隔,从几个小时到几天不等。
我认为一种便宜的方法是按开始时间对间隔列表进行排序,然后连续检查月份范围内的间隔之间是否有中断。如果是,则未完全覆盖该月。
我被困在第一部分,对列表进行排序。我计划使用 Arrays.sort(),但它需要元素来实现类似的接口。但是,在查看源代码后,Joda-Time 的 Interval 类似乎没有我可以重写的类,我无法扩展它来编写我自己的 compareTo 方法。
除了编写我自己的排序方法之外,还有人知道一种更简单的方法来实现这一点吗?谢谢
Collections#sort
与Comparator
一起使用来对时间间隔进行排序,并使用Interval#gap
来检查间隙。如果 timeInterval 完全覆盖了开始和结束之间的间隔,则以下代码返回 true:
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;
}
您可以使用下一个方法
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();
}
例
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();
}