1

I am trying to determine if two sets of date/time range overlap or not --- returning BOOLEAN value.

Consider the following cases:

NOTE: I turn each date/time string below (e.g. 24-JAN-17 07:00) to timestamp using strtotime()

Expression used for each case is: $isOverlapping = (s1 < e2 && s2 < e1)

Case 1:

Let (s1, e1) be defined as (24-JAN-17 07:00, 24-JAN-17 17:00)

Let (s2, e2) be defined as (24-JAN-17 16:30, 24-JAN-17 17:30)

Result: TRUE (which is correct)


Case 2:

Let (s1, e1) be defined as (24-JAN-17 07:00, 24-JAN-17 17:00)

Let (s2, e2) be defined as (24-JAN-17 16:30, 25-JAN-17 07:00)

Result: TRUE (which is correct)


Case 3:

Let (s1, e1) be defined as (24-JAN-17 07:00, 24-JAN-17 17:00)

Let (s2, e2) be defined as (24-JAN-17 17:00, 25-JAN-17 07:30)

Result: FALSE (which is INCORRECT)


It is my understanding that it does this because (in case of #3 above), it overflows into the next day... but if that is the case, why does it work for Case 2? (is it because the overlap happens on the same day, contrary to Case 3?)

Regardless, my question is, how to tweak my expression, such that it covers Case 3, above?

Any and all help appreciated! Thank you!


I have already reviewed the following threads, but to no avail:

Determine Whether Two Date Ranges Overlap

Determining if two time ranges overlap at any point (Specifically: https://stackoverflow.com/a/13387860/7458905)

Community
  • 1
  • 1

2 Answers2

1

The reason that your last case doesn't return TRUE is due to equality.

You say in case 3:

Let (s1, e1) be defined as (24-JAN-17 07:00, 24-JAN-17 17:00)

Let (s2, e2) be defined as (24-JAN-17 17:00, 25-JAN-17 07:30)

Which means that e1 is equal to s2 (they are both 24-JAN-17 17:00)

But your logic is only true if s2 < e1, which is NOT true in this case.

Modify your logic so that it returns true if they are equal:

$isOverlapping = (s1 <= e2 && s2 <= e1)
random_user_name
  • 25,694
  • 7
  • 76
  • 115
  • Thanks Cale for the response... I don't want it to return true if it's an edge case... in other words, Overlapping (for my requirements) CAN return false, if the end time is the same as the start time (or vice versa). Consider the following case: `Let (s1, e1) be defined as (24-JAN-17 07:00, 24-JAN-17 17:00)` `Let (s2, e2) be defined as (24-JAN-17 06:30, 24-JAN-17 07:00)` For my needs, this should not count as overlap – WebAppDev85 Jan 23 '17 at 19:13
  • So then your case #3 SHOULD return FALSE? Because it's a match, they do NOT overlap. – random_user_name Jan 23 '17 at 19:15
  • in my case 3, the overlap happens when the `e2` goes half hour into `s1` (in the following day, to be more specific) – WebAppDev85 Jan 23 '17 at 19:17
  • No, your case 3 has ZERO overlap. Look carefully. – random_user_name Jan 23 '17 at 19:22
  • Arrgggg... my mistake. I need to have that count as an overlap, as `s1` will now be `25-JAN-17 07:00` (Apologies. to me, this was an understood assumption, not realizing that not everyone will make this assumption as well) – WebAppDev85 Jan 23 '17 at 19:47
  • you know what... i wonder if the following would be the correct logic... if `e2`'s date is next date, make `s1`'s date the same (i.e. if `e2` is 25 and `s1` is 24, make `s1` as `25`... thoughts? – WebAppDev85 Jan 23 '17 at 19:50
  • Can you update the question to clarity? I'll be honest, I'm fairly confused at this point - why / how is there overlap in case #3? And your logic - while it may work - is moving towards more complex, and almost always simple beats complex.... – random_user_name Jan 23 '17 at 20:18
1

You could use some simple math to do this one, too.

Here we simply break down the components into their unix timestamps and then use the dx/dy of both to determine if they overlap

<?php
function is_overlapping($date_range_1, $date_range_2) {

    // convert into unix timestamp (milliseconds since Jan 1st 1970)
    $d1_1 = make_timestamp($date_range_1[0]);
    $d1_2 = make_timestamp($date_range_1[1]);
    $d2_1 = make_timestamp($date_range_2[0]);
    $d2_2 = make_timestamp($date_range_2[1]);

    // grab the delta of both ranges
    $delta2 = $d2_1 - $d1_2;
    $delta1 = $d2_2 - $d1_1;

    // if either has a delta < 0 then they overlap
    if (($delta2 < 0) || ($delta1 < 0)) { return "true"; }

    // catchall return value
    return "false";
}

// convert to unix timestamp function
function make_timestamp($inp_date) { 
    return strtotime($inp_date);
}

// test cases
print_r("Case 1: " .
        is_overlapping(array("24-JAN-17 07:00", "24-JAN-17 17:00"), 
                       array("24-JAN-17 16:30", "25-JAN-17 17:30"))
       );

print_r("<br>");

print_r("Case 3: " .
        is_overlapping(array("24-JAN-17 07:00", "24-JAN-17 17:00"), 
                       array("24-JAN-17 17:30", "25-JAN-17 18:30"))
       );
?>
mike510a
  • 2,102
  • 1
  • 11
  • 27