我正面临一个验证,让我的头吸烟了很多。
我有一个我现在称之为Downtime
的对象,它看起来像这样:
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实现上创建新的停机时间时,我已经验证了开始时间实际上是在结束时间之前的事情。 现在我必须添加验证,当我创建新的停机时间时,它不会干扰已经创建的停机时间。表示新停机时间的开始日期尚不存在且不是 其他停机时间。 (在已经创建的停机时间的开始和结束之间)。
所以我现在这样做的方式,因为在涉及本地化时,我在日期/时间方面很糟糕,会是这样的:
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;
}
代码是在我脑子里写的,因此可能存在语法错误,但我认为你可以理解我想要的东西。
现在回答我的问题 上面的代码看起来像这样的开销,我想知道如何更快地验证它并减少代码。
修改 让我提供一个明确的例子
我有一个像这样的停机时间列表:
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
}
]
然后我想要创建新的停机时间:
Downtime newDowntime =
{
start:2015-01-10T05:00Z,
end:2015-01-10T05:30Z
}
在此示例中,新的停机时间不有效,因为它实际上是在另一个已经创建的停机时间段内。
希望它能让事情变得更加清晰。
编辑2: 虽然标记的副本包含原因并提供了解决方案,但我也想给Hugo提供一些信用,因为考虑到我的标准,Hugo提供了一个很好的答案。
这是我准备的另一个解决方案,它提供了许多更详细的异常和信息处理
/*
* 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() );
请记住,我的“解决方案”是其中之一,并且在性能方面也非常密集,因为流是繁重的操作。因此,如果您不需要确切知道碰撞的次数以及碰撞的原因,请考虑Hugo的答案。
答案 0 :(得分:1)
或者记住这一点:当且仅当
时,两个句点将重叠(StartA&lt; = EndB)和(EndA&gt; = StartB)
因此,您必须检查新的Downtime
以防止之前的所有
答案 1 :(得分:1)
考虑到:
表示新停机时间的开始日期尚未存在,并且不在另一个停机时间。 (在已经创建的停机时间的开始和结束之间)。
在这种情况下,您需要将新downtimeFrom
的 startDate (Downtime
)与所有现有的Downtime
进行比较:
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 等于现有Downtime
的结尾,则Downtime
有效。如果您不想要,可以将第二个if
更改为:
if (downtimeStart.isBefore(newStartTime) && (! newStartTime.isAfter(downtimeEnd))) {
return false;
}
答案 2 :(得分:0)
假设你必须 LocalTime 对象,
endA 表示事件-A结束时的时间 beginB 表示事件-B开始的时间
然后
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()为负数,则它们重叠