Logic for Time Slot Availability

Hi Experts;

I need to figure out 90min free time slots, for each day in question, but I can't seem to get  it quite right.

So far I have the following 3 arrays, which show correct data below ($days, $events, $daily_slots):

$days - are the days in question:
=========START=========
days
Array
(
    [0] => 2017-12-04
    [1] => 2017-12-05
    [2] => 2017-12-06
    [3] => 2017-12-07
    [4] => 2017-12-08
)

=========END=========

Open in new window


$events - are events already in my calendar
=========START=========
events
Array
(
    [0] => Array
        (
            [name] => Meeting with Client
            [date] => 2017-12-04
            [start] => 09:00
            [end] => 12:00
        )

    [1] => Array
        (
            [name] => Working on Project
            [date] => 2017-12-05
            [start] => 10:30
            [end] => 12:30
        )

    [2] => Array
        (
            [name] => Teleconference with D
            [date] => 2017-12-05
            [start] => 15:30
            [end] => 16:30
        )

    [3] => Array
        (
            [name] => Meeting with Client
            [date] => 2017-12-06
            [start] => 10:00
            [end] => 13:00
        )

    [4] => Array
        (
            [name] => Financial Advisor
            [date] => 2017-12-06
            [start] => 14:30
            [end] => 17:00
        )

    [5] => Array
        (
            [name] => Workshop
            [date] => 2017-12-07
            [start] => 10:30
            [end] => 13:30
        )

    [6] => Array
        (
            [name] => Another Event
            [date] => 2017-12-07
            [start] => 15:30
            [end] => 16:30
        )

)

=========END=========

Open in new window


$daily_slots - these are all possible 90min time slot that any work days can have, between 9 and 4 in 30 minutes increments
=========START=========
slots
Array
(
    [0] => Array
        (
            [from] => 09:00
            [to] => 10:30
        )

    [1] => Array
        (
            [from] => 09:30
            [to] => 11:00
        )

    [2] => Array
        (
            [from] => 10:00
            [to] => 11:30
        )

    [3] => Array
        (
            [from] => 10:30
            [to] => 12:00
        )

    [4] => Array
        (
            [from] => 11:00
            [to] => 12:30
        )

    [5] => Array
        (
            [from] => 11:30
            [to] => 13:00
        )

    [6] => Array
        (
            [from] => 12:00
            [to] => 13:30
        )

    [7] => Array
        (
            [from] => 12:30
            [to] => 14:00
        )

    [8] => Array
        (
            [from] => 13:00
            [to] => 14:30
        )

    [9] => Array
        (
            [from] => 13:30
            [to] => 15:00
        )

    [10] => Array
        (
            [from] => 14:00
            [to] => 15:30
        )

    [11] => Array
        (
            [from] => 14:30
            [to] => 16:00
        )

)

=========END=========

Open in new window



As mentioned I believe that all 3 above are correct. That said, I need to get all free 90 minutes slots based on this.

I have tried the following
//Loop through each day and get available slots
        $available = array();
        $available_counter = -1;
        
        foreach($days as $day):
            
            $available_counter++;
            $available[$available_counter]['date'] = date('D. M. d', strtotime($day));
            $slots = array();
            
            foreach($daily_slots as $day_slot):
                
                foreach($events as $event):
                
                    if (strtotime($event['date']) == strtotime($day)){
                        
                        $slot_form = date($day . strtotime($day_slot['from']));
                        $slot_to = date($day . strtotime($day_slot['to']));
                        
                        
                        if (($day_slot['to'] <= $event['start']) ||
                           ($day . $day_slot['from'] >= $event['end'])){ //Day Slot is available
                    
  //                      if (strtotime($day . $day_slot['to']) <= (strtotime($event['start'])) ||
//                            (strtotime($day . $day_slot['from']) >= (strtotime($event['end'])))){ //Day Slot is available
                            
                                $slots[] = $day_slot;
                                echo 'available';
                        } else { echo 'not available'; }
                        
                    }
                
                endforeach; //event
                
            endforeach; //Daily Slots
            
            $available[$available_counter]['slots'] = $slots;
            
        endforeach; //Days
       

Open in new window


...But I am not gettign what I need, and as you can see I have tried a few things. My latest output of $available is
=========START=========
available
Array
(
    [0] => Array
        (
            [date] => Mon. Dec. 04
            [slots] => Array
                (
                    [0] => Array
                        (
                            [from] => 09:00
                            [to] => 10:30
                        )

                    [1] => Array
                        (
                            [from] => 09:30
                            [to] => 11:00
                        )

                    [2] => Array
                        (
                            [from] => 10:00
                            [to] => 11:30
                        )

                    [3] => Array
                        (
                            [from] => 10:30
                            [to] => 12:00
                        )

                    [4] => Array
                        (
                            [from] => 11:00
                            [to] => 12:30
                        )

                    [5] => Array
                        (
                            [from] => 11:30
                            [to] => 13:00
                        )

                    [6] => Array
                        (
                            [from] => 12:00
                            [to] => 13:30
                        )

                    [7] => Array
                        (
                            [from] => 12:30
                            [to] => 14:00
                        )

                    [8] => Array
                        (
                            [from] => 13:00
                            [to] => 14:30
                        )

                    [9] => Array
                        (
                            [from] => 13:30
                            [to] => 15:00
                        )

                    [10] => Array
                        (
                            [from] => 14:00
                            [to] => 15:30
                        )

                    [11] => Array
                        (
                            [from] => 14:30
                            [to] => 16:00
                        )

                )

        )

    [1] => Array
        (
            [date] => Tue. Dec. 05
            [slots] => Array
                (
                    [0] => Array
                        (
                            [from] => 09:00
                            [to] => 10:30
                        )

                    [1] => Array
                        (
                            [from] => 09:00
                            [to] => 10:30
                        )

                    [2] => Array
                        (
                            [from] => 09:30
                            [to] => 11:00
                        )

                    [3] => Array
                        (
                            [from] => 09:30
                            [to] => 11:00
                        )

                    [4] => Array
                        (
                            [from] => 10:00
                            [to] => 11:30
                        )

                    [5] => Array
                        (
                            [from] => 10:00
                            [to] => 11:30
                        )

                    [6] => Array
                        (
                            [from] => 10:30
                            [to] => 12:00
                        )

                    [7] => Array
                        (
                            [from] => 10:30
                            [to] => 12:00
                        )

                    [8] => Array
                        (
                            [from] => 11:00
                            [to] => 12:30
                        )

                    [9] => Array
                        (
                            [from] => 11:00
                            [to] => 12:30
                        )

                    [10] => Array
                        (
                            [from] => 11:30
                            [to] => 13:00
                        )

                    [11] => Array
                        (
                            [from] => 11:30
                            [to] => 13:00
                        )

                    [12] => Array
                        (
                            [from] => 12:00
                            [to] => 13:30
                        )

                    [13] => Array
                        (
                            [from] => 12:00
                            [to] => 13:30
                        )

                    [14] => Array
                        (
                            [from] => 12:30
                            [to] => 14:00
                        )

                    [15] => Array
                        (
                            [from] => 12:30
                            [to] => 14:00
                        )

                    [16] => Array
                        (
                            [from] => 13:00
                            [to] => 14:30
                        )

                    [17] => Array
                        (
                            [from] => 13:00
                            [to] => 14:30
                        )

                    [18] => Array
                        (
                            [from] => 13:30
                            [to] => 15:00
                        )

                    [19] => Array
                        (
                            [from] => 13:30
                            [to] => 15:00
                        )

                    [20] => Array
                        (
                            [from] => 14:00
                            [to] => 15:30
                        )

                    [21] => Array
                        (
                            [from] => 14:00
                            [to] => 15:30
                        )

                    [22] => Array
                        (
                            [from] => 14:30
                            [to] => 16:00
                        )

                    [23] => Array
                        (
                            [from] => 14:30
                            [to] => 16:00
                        )

                )

        )

    [2] => Array
        (
            [date] => Wed. Dec. 06
            [slots] => Array
                (
                    [0] => Array
                        (
                            [from] => 09:00
                            [to] => 10:30
                        )

                    [1] => Array
                        (
                            [from] => 09:00
                            [to] => 10:30
                        )

                    [2] => Array
                        (
                            [from] => 09:30
                            [to] => 11:00
                        )

                    [3] => Array
                        (
                            [from] => 09:30
                            [to] => 11:00
                        )

                    [4] => Array
                        (
                            [from] => 10:00
                            [to] => 11:30
                        )

                    [5] => Array
                        (
                            [from] => 10:00
                            [to] => 11:30
                        )

                    [6] => Array
                        (
                            [from] => 10:30
                            [to] => 12:00
                        )

                    [7] => Array
                        (
                            [from] => 10:30
                            [to] => 12:00
                        )

                    [8] => Array
                        (
                            [from] => 11:00
                            [to] => 12:30
                        )

                    [9] => Array
                        (
                            [from] => 11:00
                            [to] => 12:30
                        )

                    [10] => Array
                        (
                            [from] => 11:30
                            [to] => 13:00
                        )

                    [11] => Array
                        (
                            [from] => 11:30
                            [to] => 13:00
                        )

                    [12] => Array
                        (
                            [from] => 12:00
                            [to] => 13:30
                        )

                    [13] => Array
                        (
                            [from] => 12:00
                            [to] => 13:30
                        )

                    [14] => Array
                        (
                            [from] => 12:30
                            [to] => 14:00
                        )

                    [15] => Array
                        (
                            [from] => 12:30
                            [to] => 14:00
                        )

                    [16] => Array
                        (
                            [from] => 13:00
                            [to] => 14:30
                        )

                    [17] => Array
                        (
                            [from] => 13:00
                            [to] => 14:30
                        )

                    [18] => Array
                        (
                            [from] => 13:30
                            [to] => 15:00
                        )

                    [19] => Array
                        (
                            [from] => 13:30
                            [to] => 15:00
                        )

                    [20] => Array
                        (
                            [from] => 14:00
                            [to] => 15:30
                        )

                    [21] => Array
                        (
                            [from] => 14:00
                            [to] => 15:30
                        )

                    [22] => Array
                        (
                            [from] => 14:30
                            [to] => 16:00
                        )

                    [23] => Array
                        (
                            [from] => 14:30
                            [to] => 16:00
                        )

                )

        )

    [3] => Array
        (
            [date] => Thu. Dec. 07
            [slots] => Array
                (
                    [0] => Array
                        (
                            [from] => 09:00
                            [to] => 10:30
                        )

                    [1] => Array
                        (
                            [from] => 09:00
                            [to] => 10:30
                        )

                    [2] => Array
                        (
                            [from] => 09:30
                            [to] => 11:00
                        )

                    [3] => Array
                        (
                            [from] => 09:30
                            [to] => 11:00
                        )

                    [4] => Array
                        (
                            [from] => 10:00
                            [to] => 11:30
                        )

                    [5] => Array
                        (
                            [from] => 10:00
                            [to] => 11:30
                        )

                    [6] => Array
                        (
                            [from] => 10:30
                            [to] => 12:00
                        )

                    [7] => Array
                        (
                            [from] => 10:30
                            [to] => 12:00
                        )

                    [8] => Array
                        (
                            [from] => 11:00
                            [to] => 12:30
                        )

                    [9] => Array
                        (
                            [from] => 11:00
                            [to] => 12:30
                        )

                    [10] => Array
                        (
                            [from] => 11:30
                            [to] => 13:00
                        )

                    [11] => Array
                        (
                            [from] => 11:30
                            [to] => 13:00
                        )

                    [12] => Array
                        (
                            [from] => 12:00
                            [to] => 13:30
                        )

                    [13] => Array
                        (
                            [from] => 12:00
                            [to] => 13:30
                        )

                    [14] => Array
                        (
                            [from] => 12:30
                            [to] => 14:00
                        )

                    [15] => Array
                        (
                            [from] => 12:30
                            [to] => 14:00
                        )

                    [16] => Array
                        (
                            [from] => 13:00
                            [to] => 14:30
                        )

                    [17] => Array
                        (
                            [from] => 13:00
                            [to] => 14:30
                        )

                    [18] => Array
                        (
                            [from] => 13:30
                            [to] => 15:00
                        )

                    [19] => Array
                        (
                            [from] => 13:30
                            [to] => 15:00
                        )

                    [20] => Array
                        (
                            [from] => 14:00
                            [to] => 15:30
                        )

                    [21] => Array
                        (
                            [from] => 14:00
                            [to] => 15:30
                        )

                    [22] => Array
                        (
                            [from] => 14:30
                            [to] => 16:00
                        )

                    [23] => Array
                        (
                            [from] => 14:30
                            [to] => 16:00
                        )

                )

        )

    [4] => Array
        (
            [date] => Fri. Dec. 08
            [slots] => Array
                (
                )

        )

)

=========END=========

Open in new window


I had thought that the following should work: if slot ends before or at event start OR if slot starts after or at event end, then slot is available, but it is not happening.

Capture.JPG
APD TorontoAsked:
Who is Participating?
 
Julian HansenCommented:
Here is how I would do it.

Group your events as a sub-array under days.

Create a function that finds the slots in a day.

This works by working with time in minutes.

Start with 540 (9am = 9*60).
Iterate through each event.
For each event iterate from $current (starts at 9am) to the start time of the event in 30 min intervals.
As soon as $current > $start terminate the inner loop.

Set $current to the end time of that events and repeat for next event

When you have used up all the events continue doing loops from $current (which is now the end time of the last event) until end of day time (16:00 or 960 = 16*60) using the same rules - add any iteration to the slots array.

Here is some code to demonstrate
Data
<?php
// SAMPLE DATA FOR days
$days = array
(
    '2017-12-04',
    '2017-12-05',
    '2017-12-06',
    '2017-12-07',
    '2017-12-08',
);

// SAMPLE DATA FOR events
$events = array
(
    array (
    'name' => 'Meeting with Client',
    'date' => '2017-12-04',
    'start' => '09:00',
    'end' => '12:00',
  ),
  array (
    'name' => 'Working on Project',
    'date' => '2017-12-05',
    'start' => '10:30',
    'end' => '12:30',
  ),
  array (
    'name' => 'Teleconference with D',
    'date' => '2017-12-05',
    'start' => '15:30',
    'end' => '16:30',
  ),
  array (
    'name' => 'Meeting with Client',
    'date' => '2017-12-06',
    'start' => '10:00',
    'end' => '13:00',
  ),
  array (
    'name' => 'Financial Advisor',
    'date' => '2017-12-06',
    'start' => '14:30',
    'end' => '17:00',
  ),
  array (
    'name' => 'Workshop',
    'date' => '2017-12-07',
    'start' => '10:30',
    'end' => '13:30',
  ),
  array (
    'name' => 'Another Event',
    'date' => '2017-12-07',
    'start' => '15:30',
    'end' => '16:30',
  ),
);

Open in new window

Code
We use integer division (by 60) on the iteration variable ($i)  to get the hours and MOD (%) 60 on the value to get the minutes.
We use str_pad to zero pad the times
// Create the calendar of events grouped by day
$calendar = array();
foreach($events as $e) {
  if (!isset($calendar[$e['date']])) {
    $calendar[$e['date']] = array();
  }
  $calendar[$e['date']][] = $e;
}

// Go find the slots
$slots = array();
foreach($calendar as $k => $day) {
  $slots[$k] = getSlots($day);
}
// Dumpe the result
echo "<pre>" . print_r($slots, true) . "</pre>";

function getSlots($day)
{
  // Start time
  $current = 9 * 60;
  $slots = array();
  
  // Process the events
  foreach($day as $ev) {
    // Convert event start to minutes
    $bits = explode(':', $ev['start']);
    $time = $bits[0]*60+$bits[1];
    
    // Find all slots between $current and event start
    // jumping in 30 min intervals
    for($i = $current; $i + 90 <= $time; $i+=30) {
      // ... and add them to the slots array
      $slots[] = array(
        'from' => str_pad((int)($i/60),2,0, STR_PAD_LEFT) . ':' . str_pad($i % 60, 2, 0, STR_PAD_LEFT), 
        'to'  => str_pad((int)(($i+90)/60),2,0, STR_PAD_LEFT) . ':' . str_pad(($i+90)%60,2, 0,STR_PAD_LEFT)
      );
    }
    
    // Get the end time in minutes
    $bits = explode(':', $ev['end']);
    // Set current (next start) to end time of this event
    $current = $bits[0] * 60 + $bits[1];
  }
  
  // The end of the day
  $time = 16*60;
  
  // Find all open slots from end of last event till end of the day
  for($i = $current; $i + 90 <= $time; $i+=30) {
    $slots[] = array(
        'from' => str_pad((int)($i/60),2,0, STR_PAD_LEFT) . ':' . str_pad($i % 60, 2, 0, STR_PAD_LEFT), 
        'to'  => str_pad((int)(($i+90)/60),2,0, STR_PAD_LEFT) . ':' . str_pad(($i+90)%60,2, 0, STR_PAD_LEFT)
    );
  }
  
  return $slots;
}

Open in new window

Output
Array
(
    [2017-12-04] => Array
        (
            [0] => Array
                (
                    [from] => 12:00
                    [to] => 13:30
                )
            [1] => Array
                (
                    [from] => 12:30
                    [to] => 14:00
                )
            [2] => Array
                (
                    [from] => 13:00
                    [to] => 14:30
                )
            [3] => Array
                (
                    [from] => 13:30
                    [to] => 15:00
                )
            [4] => Array
                (
                    [from] => 14:00
                    [to] => 15:30
                )
            [5] => Array
                (
                    [from] => 14:30
                    [to] => 16:00
                )
        )
    [2017-12-05] => Array
        (
            [0] => Array
                (
                    [from] => 09:00
                    [to] => 10:30
                )
            [1] => Array
                (
                    [from] => 12:30
                    [to] => 14:00
                )
            [2] => Array
                (
                    [from] => 13:00
                    [to] => 14:30
                )
            [3] => Array
                (
                    [from] => 13:30
                    [to] => 15:00
                )
            [4] => Array
                (
                    [from] => 14:00
                    [to] => 15:30
                )
        )
    [2017-12-06] => Array
        (
            [0] => Array
                (
                    [from] => 13:00
                    [to] => 14:30
                )
        )
    [2017-12-07] => Array
        (
            [0] => Array
                (
                    [from] => 09:00
                    [to] => 10:30
                )
            [1] => Array
                (
                    [from] => 13:30
                    [to] => 15:00
                )
            [2] => Array
                (
                    [from] => 14:00
                    [to] => 15:30
                )
        )
)

Open in new window


Working sample here

EDIT
Updated code to use str_pad
0
 
David FavorLinux/LXD/WordPress/Hosting SavantCommented:
Usually this is accomplished by breaking up time into minimum increment of time that can booked, say 5 or 10 or 15 minutes.

Since these are all equally divisible into 90, you just scan for blocks. If your increment is 10 minutes, then you're scanning for 9 contiguous blocks of free time (9 blocks * 10 minutes == 90 minutes).

Simplify your code to using one data space (array or hash) likely generated from an SQL table containing bookings.
0
 
APD TorontoAuthor Commented:
Thank you!
0
Question has a verified solution.

Are you are experiencing a similar issue? Get a personalized answer when you ask a related question.

Have a better answer? Share it in a comment.

All Courses

From novice to tech pro — start learning today.