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 TorontoSoftware DeveloperAsked:
Who is Participating?

[Product update] Infrastructure Analysis Tool is now available with Business Accounts.Learn More

x
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

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
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

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
APD TorontoSoftware DeveloperAuthor Commented:
Thank you!
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
PHP

From novice to tech pro — start learning today.