Check if two times overlap

11,654

Solution 1

Two time periods P1 and P2 overlaps if, and only if, at least one of these conditions hold:

  1. P1 starts between the start and end of P2 (P2.from <= P1.from <= P2.to)
  2. P2 starts between the start and end of P1 (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.

Solution 2

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";
}

Solution 3

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;
}
Share:
11,654
Bird87 ZA
Author by

Bird87 ZA

By Day: Web Developer for a company in Düsseldorf, Germany. By Night: Couch potato. I love breaking away from coding just to watch some series, game a bit and just general relaxing. Also, I love stuffing my face with Pizza. For fun: Cricket. I play indoor and outdoor cricket, both just socially. Random fact: I don't have any qualifications in what I do.

Updated on June 18, 2022

Comments

  • Bird87 ZA
    Bird87 ZA almost 2 years

    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?

  • Bird87 ZA
    Bird87 ZA almost 12 years
    Might work, but then I would also need to checkk if the meeting doesn't overlap another one completely. Example: Meeting 1 starts. Meeting 2 starts, meeting 2 ends, meeting 1 ends. Looking at your code, it wont return false in this case...
  • Emil Vikström
    Emil Vikström almost 12 years
    Your conditions are unfortunately wrong. What happens if $start is before meeting_start and $end is after meeting_end? The parentheses will evaluate to false and you negate it into true! It's also a rather strange approach to fetch all non-conflicting meetings when you really just want to know if there are conflicts or not. Try to match conflicting meetings instead and use COUNT(*) and LIMIT 1 to speed it up a bit.
  • nyson
    nyson almost 12 years
    It seems like I'm a bit tired, I'm going to rewrite it >___<
  • Bird87 ZA
    Bird87 ZA almost 12 years
    This seems to be working perfectly. I've changed it a bit to allow exact same times (I'm working with engineers, and specifying 14:01 instead of just 14:00 seems to be a major brainflaw). Baie Dankie (Thank you very much in Afrikaans)
  • Emil Vikström
    Emil Vikström about 6 years
    My answer already solves this. If P1 is a full subset of P2, then my first condition holds true: P1 will start within P2.