2

I am trying to write an application for booking a time slot at an airfield, basically there is an open and close period and time interval, the application then loops between the two time values and displays a select dropdown.

I need to build in the option for the airfield to block out time ranges, so for example every Thursday between 10:00am and 12:00pm the airfield is closed to bookings, I need to build this into the loop but cannot get it working. It needs to be day specific (Mon-Sun) rather than date specific as the airfield will be closed every specified day each week for the same time period.

Here is my code so far, can anyone help please?

<?php

$open_from = "09:00";
$open_to = "17:00";
$interval = "15 mins";  

$today_number = date('w');

$intervals = array(
    array(
        'day' => '4',
        'start' => '10:00',
        'end' => '12:00',
    ),
    array(
        'day' => '4',
        'start' => '12:30',
        'end' => '13:30',
    ),
    array(
        'day' => '5',
        'start' => '15:30',
        'end' => '16:00',
    ),
);  

if(!isset($_GET['date'])){                  
    $date = date('d-m-Y');          
}else{          
    $date = $_GET['date'];          
} 

function create_time_range($start, $end, $interval) { 

    $start_time = strtotime($start); 
    $end_time   = strtotime($end); 

    $current    = time(); 
    $add_time   = strtotime('+'.$interval, $current); 
    $diff       = $add_time-$current; 

    $times = array(); 
    while ($start_time < $end_time) { 
        $times[] = $start_time; 
        $start_time += $diff; 
    } 
    $times[] = $start_time; 
    return $times; 
    
}

$times = create_time_range($open_from, $open_to, $interval);

foreach ($times as $key => $time) { 
    $times[$key] = date($date.'H:i', $time); 

    foreach($intervals as $key2 => $item) {
        if($intervals[$key2]['day']==$today_number && date('H:i',$time) == $intervals[$key2]['start'] && date('H:i',$time) == $intervals[$key2]['end']){
            echo "yes";
        }else{
            echo "no";
        }
    echo "<option value='".date('H:i', $timestamp)."'>".date('H:i',$time)."</option><br>";      
    //echo $intervals[$key]['day']." - ".$intervals[$key]['start']." - ".$intervals[$key]['end'];
    //echo "<br>";
}

    
    
}
?>
  • You need to check the week day in this loop if($intervals[$key2]['day'] and then compare the value – Shakeel Ahmad Jun 15 '23 at 13:09
  • @Shakeel - I think I am doing that already: if($intervals[$key2]['day']==$today_number && date('H:i',$time) == $intervals[$key2]['start'] && date('H:i',$time) == $intervals[$key2]['end']){ echo "yes"; }else{ echo "no"; } – simonfewkes83 Jun 15 '23 at 13:16

4 Answers4

1

In response to your question, you can achieve your desire result by using the following code:

if(!isset($_GET['date']))
    $date = date('d-m-Y');
else
    $date = $_GET['date'];

$startTime     = '09:00';
$endTime       = '17:00';
$interval      = 15; // minutes
$day           = date('N', strtotime($date));

$bookedSlots = array(
    array(
        'day' => '4',
        'start' => '10:00',
        'end' => '12:00',
    ),
    array(
        'day' => '4',
        'start' => '12:30',
        'end' => '13:30',
    ),
    array(
        'day' => '5',
        'start' => '15:30',
        'end' => '16:00',
    ),
);

function fetchTimeIntervals($startTime, $endTime, $intervalMinutes) {
    global $day,$bookedSlots;

    $htmlContent = '';

    // Convert start and end times to DateTime objects
    $start  = new DateTime($startTime);
    $end    = new DateTime($endTime);

    // Create an interval object based on the specified minutes
    $interval = DateInterval::createFromDateString($intervalMinutes.' minutes');

    // Create a date period object based on the start, end, and interval
    $period = new DatePeriod($start, $interval, $end);

    // Iterate through each interval and check each slot whether it is booked or not
    foreach ($period as $slot) {
        foreach ($bookedSlots as $subArr) {
            $isSlotBooked = false;

            $bookedSlotStartTime = new DateTime($subArr['start']);
            $bookedSlotEndTime   = new DateTime($subArr['end']);

            if($subArr['day'] == $day && $bookedSlotStartTime->getTimestamp()-$slot->getTimestamp() <= 0 && $bookedSlotEndTime->getTimestamp()-$slot->getTimestamp() > 0)
                $isSlotBooked = true;
        }

        $disableClass = ($isSlotBooked) ? 'disabled' : '';
        $slotTime     = $slot->format("H:i");
        $htmlContent .= "<option value='{$slotTime}' {$disableClass}>{$slotTime}</option>";
    }
    return $htmlContent;
}

echo $timeIntervals = fetchTimeIntervals($startTime, $endTime, $intervalMinutes);
?>
Bhavesh Patel
  • 115
  • 1
  • 2
  • 12
0

Try this way:

$interval = "15 minutes";
...
$current    = time();
add_time   = strtotime($current.'+'.$interval);

Also can you guve us more info about eventual error throwed. Eventually enable debugging:

ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);

UPDATE 1
Ok inside the foreach you try to modify the same array you are looping ($times[$key]) and doesn't seems to have sense.

Alessandro
  • 125
  • 1
  • 11
  • Thanks, the issue is with the $intervals array of start/end times and building this into the loop to check if the time being outputted is in the array range, if it is a message is displayed saying unavailable, if it isnt in the range it doesnt display a message. From this line: foreach ($times as $key => $time) { – simonfewkes83 Jun 15 '23 at 13:09
  • I am not following what you mean sorry, can you suggest some improved code please? – simonfewkes83 Jun 15 '23 at 13:17
  • I get this error with error reporting turned on: Notice: Undefined variable: timestamp in /home/v.php on line 67 – simonfewkes83 Jun 15 '23 at 13:18
  • Follow the errors then and see what comes up – Alessandro Jun 15 '23 at 13:29
0

Check this out. I hope I've understood your problem right and provided the desired solution.

<?php
$startTime     = '09:00';
$endTime       = '17:00';
$interval      = 15; // minutes
$weekNumber    = date('w');
$excludedSlots = [
    ['day' => '4', 'start' => '10:00', 'end' => '12:00'],
    ['day' => '4', 'start' => '12:30', 'end' => '13:30'],
    ['day' => '5', 'start' => '15:30', 'end' => '16:00']
];

$timeRange = generateTimeRange($startTime, $endTime, $interval, $weekNumber, $excludedSlots);
echo $timeRange;

function generateTimeRange($startTime, $endTime, $interval, $weekNumber, $excludedSlots) {
    $timeRange = '';
    $currentTime = $startTime;

    while ($currentTime <= $endTime) {
        $isExcluded = false;

        foreach ($excludedSlots as $excludedSlot) {
            if ($weekNumber == $excludedSlot['day'] && $currentTime >= $excludedSlot['start'] && $currentTime < $excludedSlot['end']) {
                $isExcluded = true;
                break;
            }
        }

        if (!$isExcluded) {
            $timeRange .= "<option value='{$currentTime}'>{$currentTime}</option>";
        } else {
            $timeRange .= "<option value='{$currentTime}' disabled>{$currentTime} (Blocked)</option>";
        }

        $currentTime = date('H:i', strtotime($currentTime) + ($interval * 60));
    }

    return $timeRange;
}
?>

Aakash Martand
  • 926
  • 1
  • 8
  • 21
0

Here is the updated code tested on local machine

<?php

$open_from = "09:00";
$open_to = "17:00";
$interval = "15 mins";  

$today_number = date('w');

$intervals = array(
    array(
        'day' => '4',
        'start' => '10:00',
        'end' => '12:00',
    ),
    array(
        'day' => '4',
        'start' => '12:30',
        'end' => '13:30',
    ),
    array(
        'day' => '5',
        'start' => '15:30',
        'end' => '16:00',
    ),
);  

if(!isset($_GET['date'])){                  
    $date = date('d-m-Y');          
}else{          
    $date = $_GET['date'];          
} 


$times = create_time_range($open_from, $open_to, $interval);

foreach ($times as $key => $time) { 
    $day = date('w', strtotime($date));
    $timeFrame = date('H:i', $time);
   
    foreach ($intervals as $slot) {
        if ($day == $slot['day'] && $timeFrame >= $slot['start'] && $timeFrame < $slot['end']) {
            echo 'No </br>';
        } else {
            echo 'Yes </br>';
        }
    }
}

function create_time_range($start, $end, $interval) { 

  $start_time = strtotime($start); 
  $end_time   = strtotime($end); 

  $current    = time(); 
  $add_time   = strtotime('+'.$interval, $current); 

  $diff       = $add_time-$current; 

  $times = array(); 
  while ($start_time < $end_time) { 
      $times[] = $start_time; 
      $start_time += $diff; 
  } 
  $times[] = $start_time; 
  return $times; 
  
}
  • that is looking better but it outputs the times 3 times, maybe as there are three arrays in the array? I only want it to get the time once: 09:00Yes 09:00Yes 09:00Yes 09:15Yes 09:15Yes 09:15Yes 09:30Yes 09:30Yes 09:30Yes 09:45Yes 09:45Yes 09:45Yes 10:00No 10:00Yes 10:00Yes 10:15No 10:15Yes 10:15Yes 10:30No 10:30Yes 10:30Yes 10:45No 10:45Yes 10:45Yes 11:00No 11:00Yes 11:00Yes – simonfewkes83 Jun 15 '23 at 13:36
  • Yes you will need to add the break in the loop I believe so – Shakeel Ahmad Jun 16 '23 at 05:25
  • If i wanted to add in dates to the excludedSlots array how would I do this, I have updated the code but it doesnt work. I need a date_from and date_to as a unix timestamp – simonfewkes83 Jun 16 '23 at 08:25