Два диапазона дат перекрываются — 1501 человек пропустил ошибку? [PHP]

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>&rarr; '.$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>&larr;&rarr;</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> &rarr; 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> &rarr; 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;
}
}}

0

Решение

У меня есть только 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

Надеюсь, это немного упростит тему.

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]