用 PHP 确定时间重叠 [英] Determining time overlap with PHP

查看:54
本文介绍了用 PHP 确定时间重叠的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 PHP 数组事件",只有 1 天,开始 &结束时间(未按时间顺序输入)如下:

$events_list = array(大批('名称' =>'事件B','开始' =>'5:00 PM','结束' =>'下午6点30分',),大批('名称' =>'事件 C','开始' =>'下午 3:30','结束' =>'5:00 PM',),大批('名称' =>'事件H','开始' =>'下午 1:15','结束' =>'2:45pm',),大批('名称' =>'事件一','开始' =>'1:30pm','结束' =>'4:00 PM',),大批('名称' =>'事件K','开始' =>'下午 4:30','结束' =>'下午 5:30',),大批('名称' =>'事件 L','开始' =>'下午 3:15','结束' =>'5:00 PM',),);

我试图在水平时间线上直观地输出这些事件,如下所示:

[* Event H: 1:15pm-2:45pm *] [* Event L: 3:15pm-5:00pm *][* Event B: 5:00pm-6:30pm *][* 活动 I:下午 1:30-4:00 *] [* 活动 K:下午 4:30-5:30 *][* 活动 C:下午 3:30-5:00 *]

(请注意,以上绝对不是按比例绘制".)

如您所见,当一个事件的开始/结束时间重叠时,它需要移动到下一行.

然而,我很难想出一种方法来实现这一点,尤其是当一个事件的开始/结束时间与另外两个事件重叠时(例如,K 的开始与事件 L"重叠,而 K 的结束与事件"重叠B"),使其向下移动 2 行而不是 1 行.

这感觉是一个相当大的挑战.非常感谢任何想法或建议!

解决方案

我已经做过这样的事情.这是我们所做的缩小版本.还有一个使用具有绝对位置的 div 来显示图表的简单版本.

'事件B','开始' =>'5:00 PM','结束' =>'下午6点30分',),大批('名称' =>'事件 C','开始' =>'下午 3:30','结束' =>'5:00 PM',),大批('名称' =>'事件H','开始' =>'下午 1:15','结束' =>'2:45pm',),大批('名称' =>'事件一','开始' =>'1:30pm','结束' =>'4:00 PM',),大批('名称' =>'事件K','开始' =>'下午 4:30','结束' =>'下午 5:30',),大批('名称' =>'事件 L','开始' =>'下午 3:15','结束' =>'5:00 PM',),);//更容易使用时间戳,循环所有行并用时间戳覆盖时间foreach($events_list as $k=>$v){$events_list[$k]['start']=strtotime($v['start']);$events_list[$k]['end']=strtotime($v['end']);}//按开始时间排序列表.降低以下所需的循环次数函数 cmp($a,$b){if($a['start']==$b['start']){$aTS = $a['end'];$bTS = $b['end'];} 别的 {$aTS = $a['start'];$bTS = $b['start'];}if($aTS == $bTS)return 0;返回 ($aTS < $bTS)?-1:1;}usort($events_list, 'cmp');//这里是保存数据的地方$levels = array();//遍历所有事件foreach($events_list 作为 $event){//此事件是否已放置在关卡中?$放置=假;//遍历每一级只检查最后一个事件foreach($levels as $row=>$events){//我们只需要检查最后一个事件是否已经排序$last = end($events);//当前事件是否在该级别最后一个事件的结束时间之后开始if($event['start'] >= $last['end']){//添加到这个级别并跳出内部循环$levels[$row][] = $event;$placed = true;休息;}}//如果没有放置在另一个级别,则添加一个新级别如果(!$放置){$levels[] = array($event);}}//用于显示目的$minutesPerPixel = 2;?><头><style type="text/css">.等级 {背景色:#DDD;宽度:<?=floor(24*60/$minutesPerPixel)?>px;边框:1px 实心 #999;位置:相对;高度:25px;}.事件 {位置:绝对;溢出:隐藏;高度:19px;顶部:2px;背景颜色:#ACF;边框:1px纯黑色;填充左:3px;字体:9px arial;行高:9px;}</风格><身体><?php//展示foreach($levels 作为 $level){echo "

\n";foreach($level as $event){$left = floor((date('H',$event['start'])*60 + date('i', $event['start']))/$minutesPerPixel);$width = floor((($event['end']-$event['start'])/60)/$minutesPerPixel);echo "\t<div class='event' style='left:{$left}px;width:{$width}px'>{$event['name']}</div>\n";}echo "</div>";}?></html>

I have a PHP array of "Events", for only 1 day, with start & end times (not entered chronologically) as follows:

$events_list = array(
array(
    'name' => 'Event B',
    'start' => '5:00pm',
    'end' => '6:30pm',
    ),
array(
    'name' => 'Event C',
    'start' => '3:30pm',
    'end' => '5:00pm',
    ),
array(
    'name' => 'Event H',
    'start' => '1:15pm',
    'end' => '2:45pm',
    ),
array(
    'name' => 'Event I',
    'start' => '1:30pm',
    'end' => '4:00pm',
    ),
array(
    'name' => 'Event K',
    'start' => '4:30pm',
    'end' => '5:30pm',
    ),
array(
    'name' => 'Event L',
    'start' => '3:15pm',
    'end' => '5:00pm',
    ),
);

I am trying to visually output these events on a horizontal timeline, something like this:

[* Event H: 1:15pm-2:45pm *]    [* Event L: 3:15pm-5:00pm *][* Event B: 5:00pm-6:30pm *]
    [* Event I: 1:30pm-4:00pm *]        [* Event K: 4:30pm-5:30pm *]
                    [* Event C: 3:30pm-5:00pm *]

(Note that the above are definitely not "drawn to scale".)

As you can see, when an event has an overlapping start/end time, it needs to move to the next line below.

However, I'm having extreme difficulty coming up with a way to accomplish this, especially when an event's start/end times overlap 2 other events (For example, K's start overlaps "Event L", and K's end overlaps "Event B"), causing it to move down 2 lines instead of just 1.

This feels like quite a challenge. Any thoughts or suggestions are very much appreciated!

解决方案

I have already done something like this. Here is a scaled down version of what we do. There is also a simple version of displaying the chart using divs with absolute position.

<?php
$events_list = array(
array(
    'name' => 'Event B',
    'start' => '5:00pm',
    'end' => '6:30pm',
    ),
array(
    'name' => 'Event C',
    'start' => '3:30pm',
    'end' => '5:00pm',
    ),
array(
    'name' => 'Event H',
    'start' => '1:15pm',
    'end' => '2:45pm',
    ),
array(
    'name' => 'Event I',
    'start' => '1:30pm',
    'end' => '4:00pm',
    ),
array(
    'name' => 'Event K',
    'start' => '4:30pm',
    'end' => '5:30pm',
    ),
array(
    'name' => 'Event L',
    'start' => '3:15pm',
    'end' => '5:00pm',
    ),
);
//easier to use timestamps, looping over all rows and overwriting time with timestamp
foreach($events_list as $k=>$v){
    $events_list[$k]['start']=strtotime($v['start']);
    $events_list[$k]['end']=strtotime($v['end']);
}

//sort list by start time. Lowers the number of loops needed below
function cmp($a,$b){
    if($a['start']==$b['start']){
        $aTS = $a['end'];
        $bTS = $b['end'];
    } else {
        $aTS = $a['start'];
        $bTS = $b['start'];
    }
    if($aTS == $bTS)return 0;
    return ($aTS < $bTS)?-1:1;
}
usort($events_list, 'cmp');

//This is where the data will be saved
$levels = array();

//loop over all the events
foreach($events_list as $event){
    //was this event placed in a level already?
    $placed = false;
    //loop through each level checking only the last event
    foreach($levels as $row=>$events){
        //we only need to check the last event if they are already sorted
        $last = end($events);
        //does the current event start after the end time of the last event in this level
        if($event['start'] >= $last['end']){
            //add to this level and break out of the inner loop
            $levels[$row][] = $event;
            $placed = true;
            break;
        }
    }
    //if not placed in another level, add a new level
    if(!$placed){
        $levels[] = array($event);
    }
}

//used for display purposes
$minutesPerPixel = 2;
?>
<html>
<head>
<style type="text/css">
.level {
    background-color:#DDD;
    width:<?=floor(24*60/$minutesPerPixel)?>px;
    border:1px solid #999;
    position:relative;
    height:25px;
}
.event {
    position:absolute;
    overflow:hidden;
    height:19px;
    top:2px;
    background-color:#ACF;
    border:1px solid black;
    padding-left:3px;
    font:9px arial;
    line-height:9px;
}
</style>
</head>
<body>
<?php
//display
foreach($levels as $level){
    echo "<div class='level'>\n";
    foreach($level as $event){
        $left = floor((date('H',$event['start'])*60 + date('i', $event['start']))/$minutesPerPixel);
        $width = floor((($event['end']-$event['start'])/60)/$minutesPerPixel);
        echo "\t<div class='event' style='left:{$left}px;width:{$width}px'>{$event['name']}</div>\n";
    }
    echo "</div>";
}
?>
</body>
</html>

这篇关于用 PHP 确定时间重叠的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆