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

如何在Java中检查间隔列表(Joda Time)是否完全覆盖一个月,java,jodatime,Java,Jodatime,我使用Java中的库来跟踪时间列表。我想检查对象列表是否完全覆盖了一个月的每一分钟。大约有30个时间间隔,从几小时到几天不等 我认为一种便宜的方法是按开始时间对间隔列表进行排序,然后依次检查该月范围内的间隔之间是否有中断。如果是,则该月未完全覆盖 我被困在第一部分,整理名单。我计划使用.sort(),但它需要元素来实现可比较的接口。然而,在查看了源代码之后,Joda Time的Interval类似乎没有一个我可以重写的类,并且我无法扩展它来编写我自己的compareTo方法 除了写我自己的排序方

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

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

我被困在第一部分,整理名单。我计划使用.sort(),但它需要元素来实现可比较的接口。然而,在查看了源代码之后,Joda Time的Interval类似乎没有一个我可以重写的类,并且我无法扩展它来编写我自己的compareTo方法

除了写我自己的排序方法,还有谁知道一个更简单的方法来完成这个任务?谢谢

您可以使用与对时间间隔进行排序,并使用检查间隔。如果开始和结束之间的间隔完全由时间间隔覆盖,则以下代码返回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;
}
发现公共静态布尔值(列出时间间隔、日期时间开始、日期时间结束){ if(timeinterval.isEmpty()){ 返回false; } //从原始列表创建排序集以获取 //无双条目的已排序区间 Set intervalSet=新树集(新比较器(){ @凌驾 公共整数比较(区间o1、区间o2){ 返回o1.getStart().compareTo(o2.getStart()); } }); intervalSet.addAll(时间间隔); 列表间隔=新的ArrayList(intervalSet); //删除其他文件中完全包含的间隔 List RemovedInterval=新建ArrayList(); 对于(int i=0;i<(interval.size()-1);i++){ 对于(intj=(i+1);j您可以使用下一种方法

静态布尔覆盖(间隔月,列出间隔)
{
//假设间隔已按开始时间排序
最终可变间隔月数=新可变间隔月数;
开始:用于(最终间隔:间隔)
{
if(interval.getStartMillis()monthInterval.getStartMillis())
{
if(interval.getEndMillis()>monthInterval.getEndMillis())
{
返回true;
}
monthInterval.setStartMillis(interval.getEndMillis());
//continue start;//循环将继续
}否则{
if(间隔重叠(月))返回false;
}
}
返回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();
   }
static final List interval=new ArrayList();
静止的
{
添加(新间隔(新日期时间(1990,05,15,00,00,00,00,00),新日期时间(1990,05,18,00,00,00,00,00,00));
添加(新时间间隔(新日期时间(1990,04,28,00,00,00,00),新日期时间(1990,05,18,00,00,00,00,00,00));
添加(新间隔(新日期时间(1990,05,17,00,00,00,00,00),新日期时间(1990,05,21,00,00,00,00,00));
添加(新的间隔(新的日期时间(1990,05,21,00,00,00,00),新的日期时间(1990,05,29,00,00,00,00,00));
添加(新间隔(新日期时间(1990,05,22,00,00,00,00,00),新日期时间(1990,05,25,00,00,00,00,00));
添加(新间隔(新日期时间(1990,05,27,00,00,00,00,00),新日期时间(1990,06,02,00,00,00,00));
}
公共静态void main(字符串[]args)
{
final DateTime startOfMonth=新日期时间(1990,05,01,00,00);
最终间隔monthInterval=新间隔(startOfMonth,startOfMonth.plusMonth(1));
封面(月底、间隔);
}
静态布尔覆盖(间隔月、列表间隔)
{
最终可变间隔月数=新可变间隔月数;
开始:用于(最终间隔:间隔)
{
if(interval.getStartMillis()monthInterval.getStartMillis())
{
if(interval.getEndMillis()>monthInterval.getStartMillis())
{
返回true;
}
monthInterval.setStartMillis(interval.getEndMillis());
继续启动;
}
}
返回monthInterval.getStartMillis()==monthInterval.getEndMillis();
}

还有一个问题我不能用评论的形式来描述)@Ilya好的,你能用文字表达吗?如果有错误,我想知道,以便更正;)间隔:1)3-10,2)4-5,3)6-11。2和3之间有一个间隙,因此这将返回
false
@Ilya您是对的,谢谢您指出这一点。我会解决它。因为你有单循环,你不需要这个标志继续。我使这个解决方案在使用Katja的建议对间隔进行初始排序后工作。否则,该alg无法判断间隙在哪里。然后在第一个if语句失败时返回false,因为它将指示上一个间隔和当前间隔之间的间隔。谢谢你的帮助!