Установите один:
Установите два:
Что мне нужно это для вывода:
Я попытался использовать функцию для проверки перекрытий как таковых:
!($lhs['RecordOnset'] > $rhs['RecordOffset'] || $lhs['RecordOffset'] < $rhs['RecordOnset'])
И использовал цикл for для проверки наложения:
for($i = 1; $i < sizeof($arr1); $i++) {
for($j = 1; $j < sizeof($arr2); $j++) {
$record = $arr1[$i];
if($result = $this->intersects($arr1[$i], $arr2[$j])) {
// $result;
}
}
}
Проблема, с которой я сталкиваюсь, заключается в том, что, когда я разбиваю диапазон дат, он не проверяет новый диапазон, созданный при цикле. У меня нет возможности использовать SQL с этим, поэтому я должен придумать программное решение. Я пробовал несколько разных методов, включая некоторые циклы foreach.
Данные принимаются в формате даты, как показано в массиве, например:
$arr1 = array(array('start'=>'04/05/2014', 'end'=> '2014-06-27'), array('start'=>'2014-06-28', 'end'=> '2014-10-19'));
$arr2 = array(array('start'=>'04/05/2014', 'end'=> '2014-05-02'), array('start'=>'2014-05-03', 'end'=> '2014-05-31'),array('start'=>'2014-06-01', 'end'=> '2014-10-19'));
Вторая пара будет отдельным массивом, поскольку она может иметь одинаковые ключи.
Любое руководство или помощь в этом с благодарностью. Диапазон дат с PHP имеет очень ограниченный ресурс онлайн.
Подготовка
$arr1 = array(
array('start'=>'2014-04-05', 'end'=> '2014-06-27'),
array('start'=>'2014-06-28', 'end'=> '2014-10-19'),
);
$arr2 = array(
array('start'=>'2014-04-05', 'end'=> '2014-05-02'),
array('start'=>'2014-05-03', 'end'=> '2014-05-31'),
array('start'=>'2014-06-01', 'end'=> '2014-10-21')
);
// merge arrays
$all = array_merge($arr1,$arr2);
// divide start-dates and end-dates into two arrays
$starts = array();
$ends = array();
foreach($all as $date){
$starts[] = $date['start'];
$ends[] = $date['end'];
}
// Remove duplicates and "sort ASC"$starts = array_unique($starts);
natsort($starts);
$ends = array_unique($ends);
natsort($ends);
echo '<pre>';
var_dump($starts,$ends);
echo '</pre>';
выход
array(4) {
[0]=>
string(10) "2014-04-05"[3]=>
string(10) "2014-05-03"[4]=>
string(10) "2014-06-01"[1]=>
string(10) "2014-06-28"}
array(5) {
[2]=>
string(10) "2014-05-02"[3]=>
string(10) "2014-05-31"[0]=>
string(10) "2014-06-27"[1]=>
string(10) "2014-10-19"[4]=>
string(10) "2014-10-21"}
Хорошо. Теперь нам нужен цикл цикла $starts
: для каждого start
найти ближайший end
что больше чем start
, Сделай это:
$ranges = array();
foreach($starts as $start){
$start_time = strtotime($start);
foreach($ends as $end){
$end_time = strtotime($end);
if ($start_time>$end_time) continue;
else{
$ranges[$end] = $start;
break;
}
}
}
// "combine"$result = array();
foreach($ranges as $end=>$start) {
$result[] = array('start' => $start, 'end' => $end);
}
// print final result
foreach($result as $item){
echo $item['start'].' To '.$item['end'].'<br/>';
}
выход:
2014-04-05 To 2014-05-02
2014-05-03 To 2014-05-31
2014-06-01 To 2014-06-27
2014-06-28 To 2014-10-19
Что вам нужно.
Заметка
Об этой строке в циклах:
$ranges[$end] = $start;
У нас может быть такая ситуация:
2014-04-03 To 2014-05-02
2014-04-04 To 2014-05-02
2014-04-05 To 2014-05-02
Но это неправильно. Нужен только последний диапазон 2014-04-05 To 2014-05-02
, И строка:
$ranges[$end] = $start;
переопределить значение с тем же ключом => наконец будет установлено правильно 2014-04-05
чтобы ключ 2014-05-02
,
Вот мое решение:
<?php
$array1 = array(
array('s'=>'2014-04-05','e'=>'2014-06-27'),
array('s'=>'2014-06-28','e'=>'2014-10-19')
);
$array2 = array(
array('s'=>'2014-04-05','e'=>'2014-05-02'),
array('s'=>'2014-05-03','e'=>'2014-05-31'),
array('s'=>'2014-06-01','e'=>'2014-10-19')
);
//merge arrays together
$merged_array = array_merge($array1,$array2);
//filter out duplicate start dates
$filtered_array = array();
foreach($merged_array as $k=>$v){
if(!isset($filtered_array[ $v['s'] ] )){
$filtered_array[ $v['s'] ] = $v;
}
//if the end date is before the currently saved end date (for this start date) then use it
if( strtotime($v['e']) < strtotime($filtered_array[ $v['s'] ]['e']) ){
$filtered_array[ $v['s'] ] = $v;
}
}
//reset the array to zero based
$filtered_array = array_values($filtered_array);
//sort the array by start date
$tmp = array();
foreach($filtered_array as $k=>$v){
$tmp[$k] = $v['s'];
}
array_multisort($tmp,SORT_ASC,$filtered_array);
//end date overlap checking
foreach($filtered_array as $k=>$v){
//if the end date is after (or equal to) the "next" start date, then make that end date the "yesterday" of the next start date
if( isset($filtered_array[$k+1]['s']) && strtotime($v['e']) >= strtotime($filtered_array[$k+1]['s']) ){
$yesterday = strtotime($filtered_array[$k+1]['s']) - 1;
$yesterday = date("Y-m-d",$yesterday);
$filtered_array[$k]['e'] = $yesterday;
}
}
echo '<pre>',print_r($filtered_array),'</pre>';
/*
Array
(
[0] => Array
(
[s] => 2014-04-05
[e] => 2014-05-02
)
[1] => Array
(
[s] => 2014-05-03
[e] => 2014-05-31
)
[2] => Array
(
[s] => 2014-06-01
[e] => 2014-06-27
)
[3] => Array
(
[s] => 2014-06-28
[e] => 2014-10-19
)
)
*/