https://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap
I wrote this post to be sure am I wrong or no one saw the bug here.
To be sure I collect all the data in functions to show results and describe my point.
All was good but when we analise all combination of dates I think there is a bug in combination 6 & 7. Mb it should never happend but when we analise a lot of datas there is point where we don't know and combination 6 will needed.
Function simulate_ranges is to check all posibilities we can check to check the aswer is good or not.
Function stack_overflow_answers - answers from topic to check results.
Ending "for" is to check all answers with all combinations.
Please uncomment other cases to check results and tell me: Am I wrong or topic from top link have wrong math to case 6?
function simulate_ranges($case) {
switch($case) {
case 1:
# A X Z B
$a='2017-01-01';
$b='2017-01-04';
$x='2017-01-02';
$z='2017-01-03';
$combo=array('a' => $a,'x' => $x,'z' => $z,'b' => $b);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
# ----- START A ------------------------------------------------------------------------------ START B --- #
# -------------------------------- END X ------------------------ END Z ----------------------------------- #
break;
case 2:
# A X B Z
$a='2017-01-01';
$b='2017-01-03';
$x='2017-01-02';
$z='2017-01-04';
$combo=array('a' => $a,'x' => $x,'b' => $b,'z' => $z);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
# ----- START A ------------------------------------------ START B --------------------------------------- #
# -------------------------------- END X ----------------------------------------------- END Z ------------ #
break;
case 3:
# X A Z B
$a='2017-01-02';
$b='2017-01-04';
$x='2017-01-01';
$z='2017-01-03';
$combo=array('x' => $x,'a' => $a,'z' => $z,'b' => $b);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
# -------------------------------------- START A --------------------------------------- START B --------- #
# ---------- END X -------------------------------------- END Z ------------------------------------------- #
break;
case 4:
# X A B Z
$a='2017-01-02';
$b='2017-01-03';
$x='2017-01-01';
$z='2017-01-04';
$combo=array('x' => $x,'a' => $a,'b' => $b,'z' => $z);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
# -------------------------------------- START A ---------------- START B -------------------------------- #
# ---------- END X ----------------------------------------------------------- ----------- END Z --------- #
break;
case 5:
# A B X Z
$a='2017-01-01';
$b='2017-01-02';
$x='2017-01-03';
$z='2017-01-04';
$combo=array('a' => $a,'b' => $b,'x' => $x,'z' => $z);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
# --------- START A --------- --------- START B --------- # # ----------------------- ---------------------------------------- #
# ---------------------------------------------------------------- # # ---------- END X ----------- ----------- END Z --------- #
break;
case 6:
# X Z A B
$a='2017-01-03';
$b='2017-01-04';
$x='2017-01-01';
$z='2017-01-02';
# ---------- END X ----------- ----------- END Z --------- # # ---------------------------------------------------------------- #
# ----------------------- ---------------------------------------- # # --------- START A --------- --------- START B --------- #
$combo=array('x' => $x,'z' => $z,'a' => $a,'b' => $b);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
break;
case 7:
# A B X Z
$a='2017-01-01';
$b='2017-01-02';
$x='2017-01-02';
$z='2017-01-03';
# --------- START A --------- --------|- START B -|---------------------------------------------- #
# -----------------------------------------|-- END X ---|-------------------------- END Z --------- #
$combo=array('a' => $a,'b' => $b,'x' => $x,'z' => $z);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
break;
case 8:
# X Z A B
$a='2017-01-01 01:00:00';
$b='2017-01-02 00:00:00';
$x='2017-01-01 00:00:01';
$z='2017-01-01 01:00:00';
# --------- END X --------- --------|- START A -|---------------------------------------------- #
# -----------------------------------------|-- END Z ---|-------------------------- START B --------- #
$combo=array('x' => $x,'a' => $a, 'z' => $z,'b' => $b);
$pair=array('a, b' =>$a.' - '.$b, 'x, z' => $x.' - '.$z);
break;
}
$a2=strtotime($a);
$b2=strtotime($b);
$x2=strtotime($x);
$z2=strtotime($z);
echo '<table>';
foreach($combo as $var => $data) {
$strtotime=${$var.'2'};
switch($var) {
case 'a': $final_var='StartA'; break;
case 'b': $final_var='StartB'; break;
case 'x': $final_var='EndA'; break;
case 'z': $final_var='EndB'; break;
}
echo '<tr><td style="text-align: right;"> ('.$final_var.') </td><td>→ '.$data.'</td><td> ('.$strtotime.')</td></tr>';
}
echo '</table>';
echo '<table><tr>';
$i=0;
foreach($pair as $vars => $dates_ranges) {
switch($vars) {
case 'a, b': $final_vars='StartA, StartB'; break;
case 'x, z': $final_vars='EndA, EndB'; break;
}
echo '<td style="text-align: right;"> ('.$dates_ranges.') </td>';
if(empty($i)) {
echo '<td>←→</td>';
}
$i=1;
}
echo '</tr></table>';
return array('a' => $a2, 'b' => $b2, 'x' => $x2, 'z' => $z2);
}
function result($result) {
if($result) {
echo '<span style="background: green; color: white; padding: 1px 10px;">Dates match</span>';
}
else {
echo '<span style="background: red; color: white; padding: 1px 10px;">Dates <b>NOT</b> match</span>';
}
echo '<hr />';
}
function stack_overflow_answers($case,$a,$b,$x,$z) {
#StartA -> a
#StartB -> b
#EndA -> x
#EndB -> z
echo '<br />';
switch($case)
{
case 'Charles Bretana - first':
echo '<b>(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB)</b><br />';
if( ( ($a <= $z) && ($b <= $x) && ($a <= $x) && ($b <= $z) ) )
result(false);
else
result(true);
break;
case 'Charles Bretana - second':
echo '<b>(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB)</b><br />';
if( ($a <= $z) && ($a <= $x) && ($b <= $x) && ($b <= $z) )
result(false);
else
result(true);
break;
case 'Charles Bretana - third':
echo '<b>(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB))</b> → Missing bracket?<br />';
if( $x <= Min($x, $z) && ( $b <= Min($x, $z) ) )
result(false);
else
result(true);
break;
case 'Charles Bretana - fourth':
echo '<b>(Max(StartA, StartB) <= Min(EndA, EndB)</b> → Missing bracket too?<br />';
if( Max($a, $b) <= Min( $x, $z) )
result(false);
else
result(true);
break;
case 'Charles Bretana - maybe all cases in once?':
echo '<b>(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB)<br />';
echo '(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB)<br />';
echo '(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB))<br />';
echo '(Max(StartA, StartB) <= Min(EndA, EndB)<br />';
echo '</b><br />';
if(
( ($a <= $z) && ($b <= $x) && ($a <= $x) && ($b <= $z) )
|| ( ($a <= $z) && ($a <= $x) && ($b <= $x) && ($b <= $z) )
|| ( $x <= Min($x, $z) && ( $b <= Min($x, $z) ) )
|| ( Max($a, $b) <= Min( $x, $z) )
)
result(false);
else
result(true);
break;
case 'Charles Bretana - using C':
echo '<b>(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)</b><br />';
$result=($a > $b? $a: $b) <= ($x < $z? $x: $z);
if($result === false)
result( true );
else
result( false );
break;
case 'Ian Nelson':
echo '<b>(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)</b><br />';
if(
($a <= $z) && ($b <= $x)
)
result(false);
else
result(true);
break;
case 'First Good Solution? Almost':
echo '<b>Min(StartA, StartB) >= Max(EndA, EndB) OR Max(StartA, StartB) <= Min(EndA, EndB)</b><br />';
if( ( Min($a, $b) >= Max($x, $z) ) || ( Max($a, $b) <= Min($x, $z) )
&& $a !== $x
&& $b !== $x
&& $a !== $z
&& $b !== $z
)
result(false);
else
result(true);
break;
case 'JustOnUnderMillions':
echo '<b>Simplyfy function sort before</b><br />';
$ranges = array(
array(array($a,$b),array($x,$z)),
);
foreach($ranges as $set){
//to change the order of the ranges for testing
shuffle($set);
//now order it
usort($set,function($a,$b){
if ($a[0] == $b[0]) { return 0; }
return ($a[0] < $b[0]) ? -1 : 1;
});
//test DR2S > DR1E no overlap
if($set[1][0] > $set[0][1]){
result(false);
} else {
result(true);
}
}
break;
}
}
for($i=1; $i <= 8; $i++) {
$case='Charles Bretana - first';
// $case='Charles Bretana - second';
// $case='Charles Bretana - third';
// $case='Charles Bretana - fourth';
// $case='Charles Bretana - maybe all cases in once?';
// $case='Charles Bretana - using C';
// $case='Ian Nelson';
// $case='First Good Solution? Almost';
// $case='JustOnUnderMillions';
if($i === 1) { echo '<hr />Case <span style="color: blue;">'.$case.'</span><hr />'; }
echo 'Combination <span style="color: red;">'.$i.'</span><br />';
$temp=simulate_ranges($i);
$a = $temp['a'];
$b = $temp['b'];
$x = $temp['x'];
$z = $temp['z'];
stack_overflow_answers($case,$a,$b,$x,$z);
}
Thanks for @JustOnUnderMillions for fast and great response!
UPDATED - 2017.04.06 13:20 - added case 8 date range and @JustOnUnderMillions calculation. His case is working good in all cases.
When we put those date ranges only @JustOnUnderMillions calculate is good
# https://stackoverflow.com/questions/43250973/two-dates-range-overlap-1501-people-missing-bug-php
$time_min='2017-01-01 01:00:00';
$time_max='2017-01-02 00:00:00';
$time_checked_min='2017-01-01 00:00:01';
$time_checked_max='2017-01-01 01:00:00';
var_dump( checkRangeBetweenRange( $time_min, $time_max, $time_checked_min, $time_checked_max ) );
function checkRangeBetweenRange( $time_min, $time_max, $time_checked_min, $time_checked_max, $convert_date=true ){
# convert date time
if($convert_date) {
$time_min=strtotime($time_min);
$time_max=strtotime($time_max);
$time_checked_min=strtotime($time_checked_min);
$time_checked_max=strtotime($time_checked_max);
}
# https://stackoverflow.com/questions/43250973/two-dates-range-overlap-1501-people-missing-bug-php
$ranges = array(
array(array($time_min,$time_max),array($time_checked_min,$time_checked_max)),
);
foreach($ranges as $set){
//to change the order of the ranges for testing
shuffle($set);
//now order it
usort($set,function($a,$b){
if ($a[0] == $b[0]) { return 0; }
return ($a[0] < $b[0]) ? -1 : 1;
});
//test DR2S > DR1E no overlap
if($set[1][0] > $set[0][1]){
return false;
} else {
return true;
}
}
}
I have only a Note
to complexity used:
It is all about check a daterange
against daterange
, so all the stuff called EndA StartA EndB
is wired.
I would first check witch date is earlier in range. And then sort it before using it, so the Charles Bretana - maybe all cases in once?
is not needed.
Just order the dateranges
before check them in detail. If you have done this, one single check will say if they overlap or not.
DR = DateRange , 1 = earlier start than 2, S = start , E = End
DR2S > DR1E = No Overlap (here we dont do >=
)
$ranges = array(
//only non overlap
array(array('2017-01-01','2017-01-02'),array('2017-01-03','2017-01-04')),
//rest overlapping
array(array('2017-01-01','2017-01-02'),array('2017-01-02','2017-01-04')),
array(array('2017-01-01','2017-01-02'),array('2017-01-01','2017-01-04')),
array(array('2017-01-01','2017-01-03'),array('2017-01-03','2017-01-04')),
);
foreach($ranges as $set){
//to change the order of the ranges for testing
shuffle($set);
//now order it
usort($set,function($a,$b){
if ($a[0] == $b[0]) { return 0; }
return ($a[0] < $b[0]) ? -1 : 1;
});
//show
print implode(' - ',$set[0]).' vs '.implode(' - ',$set[1]);
//test DR2S > DR1E no overlap
if($set[1][0] > $set[0][1]){
print ' NO OVERLAP<br>';
} else {
print ' OVERLAP<br>';
}
}
Results:
2017-01-01 - 2017-01-02 vs 2017-01-03 - 2017-01-04 NO OVERLAP
2017-01-01 - 2017-01-02 vs 2017-01-02 - 2017-01-04 OVERLAP
2017-01-01 - 2017-01-04 vs 2017-01-01 - 2017-01-02 OVERLAP
2017-01-01 - 2017-01-03 vs 2017-01-03 - 2017-01-04 OVERLAP
Hopefully this simplifies the topic a little bit.