返回基于PHP中开始和结束时间的时隙数组

时间:2012-12-17 15:01:32

标签: php

我需要你帮助解决以下问题。我正在建立一个使用PHP的网站,我想在其上显示一个显示一周中几天的日历,每天分为3个时段。这些时隙可以是免费的,也可以是预订的,在这种情况下,时间段是不可选择的。

到目前为止一切顺利,但问题在于显示预订时段。我从脚本中获取预订数据,该脚本为我提供了开始日期和时间,以及结束日期和时间。这些日期/时间戳可以是任何时间戳,也不受时间段时间的约束。它们可以在同一天,也可以跨越多天。每个时段的时间段相同:从9到13,13到17和19到23小时。

例如,假设我的开始时间为17-12-2012 13:00,结束时间为18-12-2012 11:00,我希望我的功能给我一个这样的数组:

array(1) {
  ["meetingroom1_booked"]=>
  array(3) {
    [0]=>
    array(2) {
      ["day"]=>
      string(10) "2012-12-17"
      ["timeslot"]=>
      string(1) "2"
    }
    [1]=>
    array(2) {
      ["day"]=>
      string(10) "2012-12-17"
      ["timeslot"]=>
      string(1) "3"
    }
    [2]=>
    array(2) {
      ["day"]=>
      string(10) "2012-12-18"
      ["timeslot"]=>
      string(1) "1"
    }
  }
}

我一直在绞尽脑汁,但无法想出一个处理开始时间跨越多天的好解决方案。在一天的开始和结束时间,没有问题:我可以比较开始时间和时段时间。当然,这在多天内不起作用。任何指向正确的方向都非常感谢!谢谢!

4 个答案:

答案 0 :(得分:2)

使用简单算法的另一种方法:

<?php
$start_date = '2012-12-17';
$start_time = '13:00';
$end_date = '2012-12-18';
$end_time = '11:00';
$slots = array(1=>'09:00', 2=>'13:00', 3=>'19:00');

// [helper]
$start_date_stamp = strtotime($start_date);
$end_date_stamp = strtotime($end_date);
$startdate_timestamp = strtotime($start_date . ' ' . $start_time);
$enddate_timestamp = strtotime($end_date . ' ' . $end_time);
// [/helper]

$cur_date_stamp = $start_date_stamp;
$result = array();
if ($enddate_timestamp >= $startdate_timestamp) {
    // [loop for each date]
    while($cur_date_stamp <= $end_date_stamp) {
        foreach($slots as $slkey=>$slval) {
            if ($cur_date_stamp == $start_date_stamp) { // compare for current date = start date
                $check_slot_stamp = strtotime(date('Y-m-d', $cur_date_stamp) . ' ' . $slval);
                if ($startdate_timestamp <= $check_slot_stamp) {
                    $result[] = array(
                        'day' => date('Y-m-d', $cur_date_stamp),
                        'timeslot' => $slkey
                    );
                }
            }
            elseif ($cur_date_stamp == $end_date_stamp) { // compare for current date = end date
                $check_slot_stamp = strtotime(date('Y-m-d', $cur_date_stamp) . ' ' . $slval);
                if ($check_slot_stamp <= $enddate_timestamp) {
                    $result[] = array(
                        'day' => date('Y-m-d', $cur_date_stamp),
                        'timeslot' => $slkey
                    );
                }
            }
            else { // 3 slots will be added for any date other than start_date and end_date
                $result[] = array(
                    'day' => date('Y-m-d', $cur_date_stamp),
                    'timeslot' => $slkey
                );
            }
        }
        $cur_date_stamp = strtotime('+1 day', $cur_date_stamp); // next day
    }
    // [/loop for each date]
}
$result = array('meetingroom1_booked'=>$result);
var_dump($result);

答案 1 :(得分:1)

这是我提出的可能有用的通用功能。我对'时间段'的计算可能与您想要的完全不符,但您可以更新它以满足您的需求。

$res = calc('01-12-2012 09:00', '01-12-2012 13:00');
print_r($res);
$res = calc('17-12-2012 13:00', '18-12-2012 11:00');
print_r($res);

function calc($start, $end) {
    // generic way to determine time slot; value is the high hour.
    static $slots = array(1 => 13, 2 => 17, 3 => 23);

    $oneDay = new \DateInterval("P1D");

    if (!($start instanceof \DateTime)) {
        $start = date_create($start);
    }
    if (!($end instanceof \Datetime)) {
        $end = date_create($end);
    }

    $ary = array();
    $now = clone $start;
    do {
        $res = array('day' => $now->format('Y-m-d'));
        foreach ($slots as $idx => $hour) {
            if ($now->format('H') <= $hour) {
                $res['slot'] = $idx;
                break;
            }
        }
        $ary[] = $res;

        $now->add($oneDay);
    } while ($now->format('Y-m-d') <= $end->format('Y-m-d'));

    return $ary;
}

输出:

Array
(
    [0] => Array
        (
            [day] => 2012-12-01
            [slot] => 1
        )

)
Array
(
    [0] => Array
        (
            [day] => 2012-12-17
            [slot] => 1
        )

    [1] => Array
        (
            [day] => 2012-12-18
            [slot] => 1
        )

)

答案 2 :(得分:1)

这似乎测试出来了。 http://www.laprbass.com/RAY_temp_daan.php

<?php // RAY_temp_daan.php
error_reporting(E_ALL);

/* PROBLEM DEFINITION
The timeslots are the same for each day: from 9 to 13, 13 to 17, and 19 to 23 hrs.

For example, say I have a start time of 17-12-2012 13:00, and an end time of 18-12-2012 11:00, I want my function to give me an array like this:

array(1) {
  ["meetingroom1_booked"]=>
  array(3) {
    [0]=>
    array(2) {
      ["day"]=>
      string(10) "2012-12-17"
      ["timeslot"]=>
      string(1) "2"
    }
    [1]=>
    array(2) {
      ["day"]=>
      string(10) "2012-12-17"
      ["timeslot"]=>
      string(1) "3"
    }
    [2]=>
    array(2) {
      ["day"]=>
      string(10) "2012-12-18"
      ["timeslot"]=>
      string(1) "1"
    }
  }
}
*/

// THE TIMEZONE
date_default_timezone_set('America/Chicago');

// THE START AND END TIMES
$alpha = '2012-12-17 13:00';
$omega = '2012-12-18 11:00';

// THE DEFINITION OF THE TIMESLOTS
$slots = array
( 1 => array
       ( 'lo' => '0900'
       , 'hi' => '1259'
       )
, 2 => array
       ( 'lo' => '1300'
       , 'hi' => '1659'
       )
, 3 => array
       ( 'lo' => '1900'
       , 'hi' => '2259'
       )
)
;

// MAKE AN ARRAY OF TIMESTAMPS OF THE HOURS
$tsa = strtotime($alpha);
$tsz = strtotime($omega);
$hours = range($tsa, $tsz, 3600);

// ASSIGN EACH HOUR TO A SLOT
foreach ($hours as $hour)
{
    $hhmm = date('Hi', $hour);
    foreach ($slots as $slot => $times)
    {
        if ($hhmm >= $times['lo'])
        {
            if ($hhmm <= $times['hi'])
            {
                // USE STRING NOTATION HERE SO WE CAN USE ARRAY_UNIQUE()
                $taken[$hour] = date('Y-m-d', $hour) . '|' . $slot;
            }
        }
    }
}
// REMOVE THE REDUNDANCIES
$taken = array_unique($taken);

// CONSTRUCT THE ASSOCIATIVE ARRAYS
foreach($taken as $thing)
{
    $arr = explode('|', $thing);
    $out[] = array('day' => $arr[0], 'timeslot' => $arr[1]);
}
// CONSTRUCT THE FINAL ARRAY
$out = array("meetingroom1_booked" => $out);

// SHOW THE WORK PRODUCT
echo '<pre>';
var_dump($out);

答案 3 :(得分:0)

当您将时间转换为UNIX TIMESTAMP时,您只需执行此检查即可。

目前的时间戳是:1355757162 时间戳tommorow 5 o&#39;时钟:1355846439

每个时间戳应大于1355757162且小于1355846439应该被预订。