如何检查间隔列表(Joda-Time)是否完全覆盖Java中的一个月



我正在使用Java中的Joda-Time库来跟踪时间间隔列表。我想检查间隔对象列表是否完全覆盖一个月的每一分钟。大约有 30 个不同长度的间隔,从几个小时到几天不等。

我认为一种便宜的方法是按开始时间对间隔列表进行排序,然后连续检查月份范围内的间隔之间是否有中断。如果是,则未完全覆盖该月。

我被困在第一部分,对列表进行排序。我计划使用 Arrays.sort(),但它需要元素来实现类似的接口。但是,在查看源代码后,Joda-Time 的 Interval 类似乎没有我可以重写的类,我无法扩展它来编写我自己的 compareTo 方法。

除了编写我自己的排序方法之外,还有人知道一种更简单的方法来实现这一点吗?谢谢

您可以将

Collections#sortComparator一起使用来对时间间隔进行排序,并使用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();
   }