首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >获取重叠时间的最简单方法

获取重叠时间的最简单方法
EN

Stack Overflow用户
提问于 2017-05-19 09:49:49
回答 3查看 98关注 0票数 2

我正面临着一种肯定,那就是我的脑袋抽了不少烟。我有一个对象,我现在称之为Downtime,它看起来如下:

代码语言:javascript
复制
public class Downtime {

  /** The start date of the downtime. */
  private ZonedDateTime downtimeFrom;

  /** The end date of the downtime. */
  private ZonedDateTime downtimeTo;

  /**
   * Gets the downtime from.
   *
   * @return the downtime from
   */
  public ZonedDateTime getDowntimeFrom()
  {
    return downtimeFrom;
  }

  /**
   * Gets the downtime to.
   *
   * @return the downtime to
   */
  public ZonedDateTime getDowntimeTo()
  {
    return downtimeTo;
  }

  /**
   * Sets the downtime from.
   *
   * @param downtimeFrom the new downtime from
   */
  protected void setDowntimeFrom( ZonedDateTime downtimeFrom )
  {
    this.downtimeFrom = downtimeFrom;
  }

  /**
   * Sets the downtime to.
   *
   * @param downtimeTo the new downtime to
   */
  protected void setDowntimeTo( ZonedDateTime downtimeTo )
  {
    this.downtimeTo = downtimeTo;
  }
}

当我在CRUD实现上创建一个新的停机时,我已经验证了开始时间实际上是在结束时间之前。

现在,我必须添加一个验证,即当我创建一个新的停机时,它不会干扰已经创建的停机时间。这意味着新的停机时间的开始日期还不存在,在中不是,另一个停机时间。(在已经创建的停机时间的开始和结束之间)。

因此,我现在这样做,因为我在面向日期/时间的事情上很糟糕,当涉及到本地化的时候,应该是这样的:

代码语言:javascript
复制
private boolean isNewDowntimeValid(Downtime newDowntime, List<Downtime> createdDowntimes){
  // let's just assume I already filtered out that the list only contains the same day. That's actually pretty easy.
  List<ZonedDateTime> dateRange = new LinkedList<>();
  ZonedDateTime newTime = newDowntime.getDowntimeFrom();

  for(Downtime downtime : createdDowntimes){
    ZonedDateTime downtimeStart = downtime.getDowntimeFrom();
    ZonedDateTime downtimeEnd = downtime.getDowntimeTo();

    for(ZonedDateTime start = downtimeStart; !start.isAfter(downtimeEnd); start = start.plusHours(1)){
      dateRange.add(start);
    }
  }
  if(dateRange.contains(newTime)){
    return false;
  }
  return true;
}

这段代码是我脑子里写出来的,所以可能有语法错误,但我想你可以知道我想要什么。

现在来问我的问题。

上面的代码似乎是这样的开销,我想知道如何用更少的代码更快地验证它。

编辑:让我提供一个清晰的示例

我有一张这样的停工清单:

代码语言:javascript
复制
List<Downtime> createdDowntimes = [
{
  start:2015-01-10T00:00Z,
  end:2015-01-10T02:00Z
},
{
  start:2015-01-10T04:00Z,
  end:2015-01-10T06:00Z
},
{
  start:2015-01-10T07:00Z,
  end:2015-01-10T09:00Z
}
]

然后我有了我想要创建的新的停机时间:

代码语言:javascript
复制
Downtime newDowntime = 
{ 
  start:2015-01-10T05:00Z,
  end:2015-01-10T05:30Z
}

在本例中,新的停机时间是,而不是,因为它实际上是在另一个已经创建的停机期间。

希望这能让事情更清楚。

编辑2:标记的副本包含了原因,并提供了一个解决方案,我也想给雨果学分,他考虑了我的标准,给出了一个很好的答案。

这里是我准备的另一个解决方案,它提供了许多更详细的异常和信息处理。

代码语言:javascript
复制
/*
 * Collision 1 = the new downtime starts before the created ones but ends in their span
 * Collision 2 = the new downtime starts after created ones and also ends after their span
 * Collision 3 = the new downtime starts after created ones and ends in their span
 */
List<Downtime> collision1 = createdDowntimes.stream().filter( e -> e.getDowntimeFrom().isAfter( newTimeStart ) )
    .filter( e -> e.getDowntimeTo().isAfter( newTimeEnd ) ).collect( Collectors.toList() );

List<Downtime> collision2 = createdDowntimes.stream().filter( e -> e.getDowntimeFrom().isBefore( newTimeStart ) )
    .filter( e -> e.getDowntimeTo().isBefore( newTimeEnd ) ).collect( Collectors.toList() );

List<Downtime> collision3 = createdDowntimes.stream().filter( e -> e.getDowntimeFrom().isBefore( newTimeStart ) )
    .filter( e -> e.getDowntimeTo().isAfter( newTimeEnd ) ).collect( Collectors.toList() );

请记住,我的“解决方案”是众多的解决方案之一,而且在性能方面也相当密集,因为流是繁重的操作。所以,如果你不需要知道到底发生了多少次碰撞,为什么会发生碰撞,那就考虑一下雨果的答案。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2017-05-19 12:15:56

考虑到:

这意味着新的停机时间的开始日期已经不存在,并且不在另一个停机时间。(在已经创建的停机时间的开始和结束之间)。

在这种情况下,您需要将新的startDate (downtimeFrom)与现有的Downtime进行比较:

代码语言:javascript
复制
private boolean isNewDowntimeValid(Downtime newDowntime, List<Downtime> createdDowntimes) {
    // the start of the new downtime
    ZonedDateTime newStartTime = newDowntime.getDowntimeFrom();

    for (Downtime downtime : createdDowntimes) {
        ZonedDateTime downtimeStart = downtime.getDowntimeFrom();
        ZonedDateTime downtimeEnd = downtime.getDowntimeTo();

        if (newStartTime.equals(downtimeStart)) {
            // start date of new downtime already exists
            return false;
        }

        // start date of new downtime is in the existent downtime
        // (existent startDate < new startDate and new startDate < existent endDate)
        if (downtimeStart.isBefore(newStartTime) && newStartTime.isBefore(downtimeEnd)) {
            return false;
        }
    }

    // no invalid cases found, it's valid
    return true;
}

注意:在此代码中,如果新的startDate是等于存在的< code >D17的末尾,则Downtime是有效的。如果不想这样,可以将第二个if更改为:

代码语言:javascript
复制
if (downtimeStart.isBefore(newStartTime) && (! newStartTime.isAfter(downtimeEnd))) {
    return false;
}
票数 1
EN

Stack Overflow用户

发布于 2017-05-19 10:06:50

检查this question

或者记住这一点:两个周期将重叠当且仅当

(StartA <= EndB)和(EndA >= StartB)

因此,您必须检查您的新Downtime与之前所有的

票数 1
EN

Stack Overflow用户

发布于 2017-05-19 10:02:25

假设您必须使用LocalTime对象,

endA表示事件-A结束时,beginB表示事件-B开始时

然后

代码语言:javascript
复制
LocalTime endA = ...;//LocalTime.of(13, 00, 00);
LocalTime beginB = ...;//LocalTime.of(12, 00, 00);
Duration duration = Duration.between(endA, beginB);
System.out.println(duration.getSeconds());

如果getSeconds()为负值,则它们重叠

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/44066779

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档