将时间范围拆分为其他时间范围

时间:2012-10-29 20:43:25

标签: php arrays datetime time

我有一项复杂的任务,我现在已经在墙上撞了几天。我尝试过4种不同的方法,但每种方法似乎都停滞不前,而且变得非常令人沮丧。

我有时间范围。例如,14:30:00到18:30:00。考虑这个时间范围某人的工作转变。在此时间范围内,他们表示他们无法在15:30:00至16:30:00和17:30:00至18:30:00之间工作。我需要修改原始班次的开始和结束时间以消除冲突的班次。

原始移位数组如下所示:

$original_shift[0]['start'] = '14:30:00';
$original_shift[0]['end']   = '18:30:00';

从原始班次中移除的时间范围如下所示:

$subshift[0]['start'] = '15:30:00';
$subshift[0]['end']   = '16:30:00';
$subshift[1]['start'] = '17:30:00';
$subshift[1]['end']   = '18:30:00';

这是一个可视化:

enter image description here

所以,当我完成时,我基本上需要我的原始轮班看起来像这样:

$original_shift[0]['start'] = '14:30:00';
$original_shift[0]['end']   = '15:30:00';
$original_shift[1]['start'] = '16:30:00';
$original_shift[1]['end']   = '17:30:00';

我还需要考虑的一些并发症是:

  1. 这些时间范围可以是任何时间(不限于我在我的例子中使用的半小时),但我会100%确定地知道不可用的时间范围将始终开始和结束或在原始班次的开始和结束时间之间。

  2. 不可用的时间可能会缩短和/或占用整个原始班次的时间。

  3. 我不是在寻找某人“编写我的代码”,因为我正在寻找过去处理过类似事情的人,并且可能对他们如何完成它有一些了解。

3 个答案:

答案 0 :(得分:3)

由于你特别要求“一些见解”而不是一个完整的工作答案,我个人会选择填充“分钟”的数组。

$shift = array(
    'start' => '15:30:00',
    'end' => '18:30:00',

    'original' => array(),
    'unavailable' => array(),
    'modified' => array()
);

然后你会做一些jiggery pokery将15:30:00转换为930并将18:30:00转换为1110(分钟数),这将为您提供开始和结束时间之间的差异。

使用range()快速填充original数组,以类似格式加载unavailable,然后使用array_intersect()array_diff()之类的内容找出原来班次的哪几分钟不可用。

由此,构建modified数组,并从那里直接读取到输出。

答案 1 :(得分:3)

您需要计算时间范围。如图所示,这似乎是一个简单的减法。只有拥有这些的对象会很好。

我没有这个准备好的代码,所以下面的概念有点粗糙,虽然可能没那么糟糕。

表示从 - 到的时间的Range类型。这些是DateTime,因此可以使用这些现有类型的好处。到目前为止,我没有使用太多的好处,但是对于其余的应用程序,这是有道理的。

Range类型已经包含了一些我认为可用于执行部分计算的基本比较方法。

然而,由于一个对象不能将自己分成两个,我还创建了一个Ranges类型,它可以代表一个或多个Range。这对于拥有可以“分裂”的东西是必要的。

我在这里作了一点欺骗,因为我将差异计算作为Range的成员实现,返回一个包含一个或多个Range对象的数组。然后,最后的计算只是换班并从中减去不可用的范围:

$shift = new Ranges(new DateTime('14:30:00'), new DateTime('18:30:00'));

$unavailables = new Ranges([
    new Range(new DateTime('15:30:00'), new DateTime('16:30:00')),
    new Range(new DateTime('17:30:00'), new DateTime('18:30:00')),
]);

$shift->subtract($unavailables);

转变然后跨越:

14:30:00 - 15:30:00
16:30:00 - 17:30:00

Demo; Gist

我不能说是否值得抽象,DateTime个对象的好处是你可以将它们与><=进行比较。当您需要在范围和范围之间进行更多计算时,这些类的真正好处可能会曝光。也许界面还不甜,但是背后的基本计算已在代码中概述。

一个警告:我的代码中14:00-15:0014:00-15:00之间的差异将导致14:00-14:00。我保持开始时间不空,但你也可以空着。 Ranges对象应该很好地处理它。

答案 2 :(得分:1)

代码应该说明一切:

$original_shift[0]['start'] = '14:30:00';
$original_shift[0]['end'] = '18:30:00';

$breaks[0]['start'] = '14:30:00';
$breaks[0]['end'] = '15:30:00';
$breaks[1]['start'] = '16:30:00';
$breaks[1]['end'] = '17:30:00';

$modified_shift = array(
    array('start' => $original_shift[0]['start'])
);

for($x = 0, $y = count($breaks), $z = 0; $x < $y; $x++){
    $modified_shift[$z]['end'] = $breaks[$x]['start'];
    if($modified_shift[$z]['end'] != $modified_shift[$z]['start']){
        $z++;       
    }
    $modified_shift[$z]['start'] = $breaks[$x]['end'];
}

$modified_shift[$z]['end'] = $original_shift[0]['end'];

if($modified_shift[$z]['end'] == $modified_shift[$z]['start']){
    unset($modified_shift[$z]);
}