I want to see if a time I read from a db overlaps with a time provided by a user.
My database looks like this:
-----------------------------------------------
|organiser|meeting_start|meeting_end|boardroom|
-----------------------------------------------
| John Doe| 1340193600 | 1340195400| big |
-----------------------------------------------
My code looks like this:
date_default_timezone_set('Africa/Johannesburg');
$from = strtotime($_GET['meeting_date'] . ' ' . $_GET['meeting_start']);
$to = strtotime($_GET['meeting_date'] . ' ' . $_GET['meeting_end']);
$another_meeting = false;
$meeting_date = strtotime($_GET['meeting_date']);
$meeting_next = $meeting_date + 86400;
$result = mysql_query("SELECT meeting_start, meeting_end FROM admin_boardroom_booking WHERE boardroom = '" . $_GET['boardroom'] . "' AND meeting_start >= '" . $meeting_date . "' AND meeting_end < '" . $meeting_next . "'")or die(mysql_error());
while($row = mysql_fetch_array($result)) {
$from_compare = $row['meeting_start'];
$to_compare = $row['meeting_end'];
$intersect = min($to, $to_compare) - max($from, $from_compare);
if ( $intersect < 0 )
$intersect = 0;
$overlap = $intersect / 3600;
if ( $overlap <= 0 ) {
$another_meeting = true;
break;
}
}
if ($another_meeting)
echo 'ERROR';
If I type two overlapping times on purpose, it doesn't echo error. What am I doing wrong?
1) Sort all intervals in increasing order of start time. This step takes O(nLogn) time. 2) In the sorted array, if start time of an interval is less than end of previous interval, then there is an overlap.
With SUMPRODUCT we can check if each start date is less than any of the end dates in the table AND, if each end date is greater than any of the start dates in the table. If the dates on each row meets this criteria for more than one set of dates in the table, then we know there are overlapping dates.
You can do this by swapping the ranges if necessary up front. Then, you can detect overlap if the second range start is: less than or equal to the first range end (if ranges are inclusive, containing both the start and end times); or. less than (if ranges are inclusive of start and exclusive of end).
The basic idea is 1) first take input_start to test_start (if both of them are not equal and input_start is min) 2) always take test_start and test_end 3) take test_end to input_end if test_end is less than input end (and end_input and end_test are not equal).
Two time periods P1 and P2 overlaps if, and only if, at least one of these conditions hold:
P2.from <= P1.from <= P2.to
)P1.from <= P2.from <= P1.to
)This will catch partly overlapping periods as well as periods where one completely covers the other. One of the periods must always start (or end) inside the other if they are overlapping.
So $another_meeting
would be defined by:
$another_meeting = ($from >= $from_compare && $from <= $to_compare) ||
($from_compare >= $from && $from_compare <= $to);
You may want to change the borderline cases to strict <
checks if one event can start at the exact same time as another ends.
Was just doing something similar.... but just with times....
$startTime = strtotime("7:00");
$endTime = strtotime("10:30");
$chkStartTime = strtotime("10:00");
$chkEndTime = strtotime("12:10");
if($chkStartTime > $startTime && $chkEndTime < $endTime)
{
// Check time is in between start and end time
echo "1 Time is in between start and end time";
}
elseif(($chkStartTime > $startTime && $chkStartTime < $endTime) || ($chkEndTime > $startTime && $chkEndTime < $endTime))
{
// Check start or end time is in between start and end time
echo "2 ChK start or end Time is in between start and end time";
}
elseif($chkStartTime==$startTime || $chkEndTime==$endTime)
{
// Check start or end time is at the border of start and end time
echo "3 ChK start or end Time is at the border of start and end time";
}
elseif($startTime > $chkStartTime && $endTime < $chkEndTime)
{
// start and end time is in between the check start and end time.
echo "4 start and end Time is overlapping chk start and end time";
}
I'd probably solve it with something like this:
function avaliable($start, $end) {
// checks if there's a meeting between start or end
$q = "SELECT * FROM admin_boardroom_booking "
. "WHERE NOT (meeting_start BETWEEN '$end' AND '$start' "
. "OR meeting_end BETWEEN '$end' AND '$start')";
$result = mysql_query($q);
// returns true on no conflicts and false elseway
return mysql_num_rows($result) === 0;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With