https://stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap
Я написал этот пост, чтобы быть уверенным, что я не прав или никто не видел ошибку здесь.
Чтобы быть уверенным, я собираю все данные в функции, чтобы показать результаты и описать мою точку зрения.
Все было хорошо, но когда мы анализируем все комбинации дат, я думаю, что есть ошибка в комбинации 6 & 7. Мб никогда не должно произойти, но когда мы анализируем много данных, есть момент, когда мы не знаем, и потребуется комбинация 6.
Функция simulate_ranges предназначена для проверки всех возможностей, которые мы можем проверить, чтобы убедиться, что ответ хороший или нет.
Функция stack_overflow_answers — ответы из темы для проверки результатов.
Окончание «за» — проверка всех ответов со всеми комбинациями.
Пожалуйста, раскомментируйте другие случаи, чтобы проверить результаты и сказать мне:
Я ошибаюсь или в теме из верхней ссылки неверная математика для случая 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);
}
Спасибо за @JustOnUnderMillions за быстрый и отличный ответ!
ОБНОВЛЕНО — 2017.04.06 13:20 — добавлен диапазон дат для случая 8 и расчет @JustOnUnderMillions. Его дело работает хорошо во всех случаях.
Когда мы помещаем эти диапазоны дат, рассчитывается только @JustOnUnderMillions
# 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;
}
}}
У меня есть только Note
Для сложности используется:
Это все о проверке daterange
против daterange
так что все называется EndA StartA EndB
подключен
Я бы сначала проверил дату ведьмы раньше в диапазоне. А затем отсортировать его перед использованием, поэтому Charles Bretana - maybe all cases in once?
не нужен
Просто закажите dateranges
прежде чем проверить их подробно.
Если вы сделали это, одна проверка скажет, перекрываются ли они или нет.
DR = DateRange, 1 = более раннее начало, чем 2, S = начало, E = конец
DR2S> DR1E = Нет перекрытия (здесь мы не делаем >=
)
$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>';
}
}
Результаты:
2017-01-01 — 2017-01-02 vs 2017-01-03 — 2017-01-04 НЕТ ПЕРЕКРЫТИЯ
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
Надеюсь, это немного упростит тему.
Других решений пока нет …