I'm trying to leverage Google Calendar (and Google Calendar API) for simple scheduling. I'm using PHP, MySQL and google-api-php-client. I'm looking for a algorithm or pseudocode to find open time slots.
My calendar has events for busy times such as when business is closed and for current appointments. I am able to retrieve event start and end times via two function (Events: list and Freebusy: query). Here is a example list of events for today with start time of 2016-02-19T01:00:00-07:00 and end time of 2016-02-19T23:00:00-07:00 (everything for the current day).
Business is Closed from 12:00am to 11:00am
start: "2016-02-19T00:00:00-07:00"
end: "2016-02-19T11:00:00-07:00"
Appointment from 1:30pm to 2:30pm
start: "2016-02-19T13:30:00-07:00"
end: "2016-02-19T14:30:00-07:00"
Appointment from 5:00pm to 7:00pm
start: "2016-02-19T17:00:00-07:00"
end: "2016-02-19T19:00:00-07:00"
Appointment from 9:00pm to 11:00pm
start: "2016-02-19T21:00:00-07:00"
end: "2016-02-19T23:00:00-07:00"
My open time slots based on this example event set is: 11:00am to 1:30pm, 2:30pm to 5:00pm, 7:00pm to 9:00pm and 11:00pm to 12:00am.
- How do I find this set of times programmatically?
Ideally I would like to get a full list of events for a given day with one API call and interpret/manipulate the list instead of making many calls with specific start and end times which would give me the information I'm looking for but be very inefficient.
- After I find the set, how do I display results in 30 minute increments i.e. available appointment start times are:
11:00,11:30,12:00,12:30,1:00,2:30,3:00,3:30,4:00,4:30,9:00,9:30,10:00,10:30,11:00,11:30
I'm having a hard time wrapping my head around working with dates/time data sets.
Here is an image of the Google Calendar. Date in question is 2/19/2016
Thank you kindly. Any source that is a result of this discussion will be posted for reference.
I would convert the dates to unix timestamps and calculate the difference between the start and end dates. This is how I would accomplish the first part of your question:
$events = array(
array(
'start' => '2016-02-19T00:00:00-07:00',
'end' => '2016-02-19T11:00:00-07:00'
),
array(
'start' => '2016-02-19T13:30:00-07:00',
'end' => '2016-02-19T14:30:00-07:00'
),
array(
'start' => '2016-02-19T17:00:00-07:00',
'end' => '2016-02-19T19:00:00-07:00'
),
array(
'start' => '2016-02-19T21:00:00-07:00',
'end' => '2016-02-19T23:00:00-07:00'
)
);
$free_time_slots = array();
$count = count($events)-1;
$i = 0;
foreach($events as $event) {
if ($i < $count) {
$free_time = strtotime($events[$i+1]['start']) - strtotime($event['end']);
$free_time_slots[] = array(
'start' => date("F j, Y, g:i a", strtotime($event['end'])),
'end' => date("F j, Y, g:i a", strtotime($events[$i+1]['start'])),
'minutes' => $free_time / 60
);
$i++;
}
}
echo '<pre>';
print_r($free_time_slots);
Which will result in this:
Array
(
[0] => Array
(
[start] => February 19, 2016, 11:00 am
[end] => February 19, 2016, 1:30 pm
[minutes] => 150
)
[1] => Array
(
[start] => February 19, 2016, 2:30 pm
[end] => February 19, 2016, 5:00 pm
[minutes] => 150
)
[2] => Array
(
[start] => February 19, 2016, 7:00 pm
[end] => February 19, 2016, 9:00 pm
[minutes] => 120
)
)
This should get the job done. You can loop through each appointment slot in the range of time you want to search. Inside that loop, you can check each of your current appointments to see if there are conflicts. This code will echo the open appointments after each iteration, but you'll probably want to push them into an array so you can use them wherever needed.
// Set timezone = UTC for consistency
date_default_timezone_set("UTC");
// Range to search for open times in.
$start_time = strtotime("2016-02-19T00:00:00-07:00");
$end_time = strtotime("2016-02-19T23:59:59-07:00");
// Test data
$events = array(
"event_1" => array(
"start" => "2016-02-19T00:00:00-07:00",
"end" => "2016-02-19T11:00:00-07:00"
),
"event_2" => array(
"start" => "2016-02-19T13:30:00-07:00",
"end" => "2016-02-19T14:30:00-07:00"
),
"event_3" => array(
"start" => "2016-02-19T17:00:00-07:00",
"end" => "2016-02-19T19:00:00-07:00"
),
"event_4" => array(
"start" => "2016-02-19T21:00:00-07:00",
"end" => "2016-02-19T23:00:00-07:00"
),
);
// Kick off first appt time at beginning of the day.
$appt_start_time = $start_time;
// Loop through each appt slot in the search range.
while ($appt_start_time < $end_time) {
// Add 29:59 to the appt start time so we know where the appt will end.
$appt_end_time = ($appt_start_time + 1799);
// For each appt slot, loop through the current appts to see if it falls
// in a slot that is already taken.
$slot_available = true;
foreach ($events as $event => $times) {
$this_start = strtotime($times['start']);
$this_end = strtotime($times['end']);
// If the appt start time or appt end time falls on a current appt, slot is taken.
if (($appt_start_time >= $this_start && $appt_start_time < $this_end) ||
($appt_end_time >= $this_start && $appt_end_time < $this_end)) {
$slot_available = false;
break; // No need to continue if it's taken.
}
}
// If we made it through all appts and the slot is still available, it's an open slot.
if ($slot_available) {
$date = new DateTime();
$date->setTimestamp($appt_start_time);
$date->setTimezone(new DateTimeZone("America/Denver"));
echo "Open appt at: ". $date->format("Y-m-d h:i:s-e") ."<br />";
}
// + 30 minutes
$appt_start_time += (60 * 30);
}
This results in:
Open appt at: 2016-02-19 11:00:00-America/Denver
Open appt at: 2016-02-19 11:30:00-America/Denver
Open appt at: 2016-02-19 12:00:00-America/Denver
Open appt at: 2016-02-19 12:30:00-America/Denver
Open appt at: 2016-02-19 01:00:00-America/Denver
Open appt at: 2016-02-19 02:30:00-America/Denver
Open appt at: 2016-02-19 03:00:00-America/Denver
Open appt at: 2016-02-19 03:30:00-America/Denver
Open appt at: 2016-02-19 04:00:00-America/Denver
Open appt at: 2016-02-19 04:30:00-America/Denver
Open appt at: 2016-02-19 07:00:00-America/Denver
Open appt at: 2016-02-19 07:30:00-America/Denver
Open appt at: 2016-02-19 08:00:00-America/Denver
Open appt at: 2016-02-19 08:30:00-America/Denver
Open appt at: 2016-02-19 11:00:00-America/Denver
Open appt at: 2016-02-19 11:30:00-America/Denver