我需要你帮助解决以下问题。我正在建立一个使用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"
}
}
}
我一直在绞尽脑汁,但无法想出一个处理开始时间跨越多天的好解决方案。在一天的开始和结束时间,没有问题:我可以比较开始时间和时段时间。当然,这在多天内不起作用。任何指向正确的方向都非常感谢!谢谢!
答案 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应该被预订。