4

次の問題についてあなたの助けが必要です。PHPを使用して、曜日を示すカレンダーを表示したいWebサイトを構築しています。各日は、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"
    }
  }
}

私はこれについて頭を悩ませてきましたが、開始と終了の時間が複数日にわたるという良い解決策を思い付くことができません。開始時刻と終了時刻が1日であるため、問題はありません。開始時刻と終了時刻をタイムスロット時間と比較できます。もちろん、これは複数日は機能しません。正しい方向へのポインタは大歓迎です!ありがとう!

4

4 に答える 4

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);
于 2012-12-17T16:28:37.580 に答える
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
        )

)
于 2012-12-17T15:43:29.803 に答える
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);
于 2012-12-17T15:45:55.727 に答える
0

時間をUNIXTIMESTAMPに変換するときは、このチェックを簡単に行うことができます。

現在のタイムスタンプは次のとおりです。1355757162タイムスタンプ明日5時:1355846439

1355757162より大きく1355846439より小さいすべてのタイムスタンプを予約する必要があります。

于 2012-12-17T15:13:22.400 に答える