我有几个以DateTime $begin, DateTime $end
的日期范围。这些范围可以以各种可能的方式重叠:
|-------|
|=======|
|------|
|======|
|------------|
|=======|
|---|
字符串
等等。
我想做的是获取第一个范围的开始和最新一个范围的结束之间的长度(以秒或DateInterval
为单位)(在上面的例子中是第四个),不包括任何范围未覆盖的区域。
只有两个范围没有问题,但是我不知道如何扩展它来处理两个以上的范围。
编辑:
class Range {
public DateTime $begin;
public DateTime $end;
}
$ranges = getRanges(); # function that returns array of Range objects
function getActiveHours($_ranges = array()) {
$sum = 0;
# this is the function I'd like to have
return $sum;
}
型
对于两个范围,我只有一个返回DateInterval
对象的函数:
function addTimeRanges(DateTime $b1, DateTime $e1, DateTime $b2, DateTime $e2) {
$res = null;
if ($e1 < $b2 || $e2 < $b1) { # separate ranges
$r1 = $b1->diff($e1);
$r2 = $b2->diff($e2);
$res = addIntervals($r1, $r2);
} else if ($b1 <= $b2 && $e1 >= $e2) { # first range includes second
$res = $b1->diff($e1);
} else if ($b1 > $b2 && $e1 < $e2) { # second range includes first
$res = $b2->diff($e2);
} else if ($b1 < $b2 && $e1 <= $e2 && $b2 <= $e1) { # partial intersection
$res = $b1->diff($e2);
} else if ($b2 < $b1 && $e2 <= $e1 && $b1 <= $e2) { # partial intersection
$res = $b2->diff($e1);
}
return $res;
}
型
其中addIntervals
是一个函数,它将两个DateInterval
对象的和作为另一个DateInterval
对象返回。
这是一些基本的版本,在我的生产代码中,我使用了很多其他不相关的东西。
为了简化,假设我们只有DateTime
的Time部分:('06:00:00'到'08:00:00')、('07:00:00'到'09:00:00')、('06:00:00'、'08:00:00')、('11:00:00'到'12:00:00')(将存在许多这样的范围)。我现在想要的结果是4个小时(从6:00到9:00 +从11:00到12:00)。
4条答案
按热度按时间a64a0gku1#
字符串
moiiocjp2#
我建议您创建一个函数,该函数返回Range类的示例,该示例的属性设置为整个周期的开始和结束。就像这样:-
字符串
我选择创建一个最小的工厂类,它可以为您执行以下类型的计算:
型
一些代码来演示它的工作原理:
型
在我运行它的时候,我得到了以下结果:
型
这将科普任何顺序的任意数量的Range对象,并始终返回一个Range对象,该对象提供所提供的所有范围所跨越的最早和最晚日期。
我还添加了一些方法,允许您以DateInterval示例或秒数的形式获取结果。
uz75evzq3#
给定任务的示例
字符串
iklwldmw4#
下面的代码可以在将日期转换为时间戳后用作解决方案的一部分:https://stackoverflow.com/a/3631016/1414555
一旦$data是带有时间戳的数组,你就可以使用它了:
字符串