Chris Beckett Chris Beckett - 1 year ago 62
PHP Question

Pick the closest date/times without any overlapping and duplicates occurring

What I've got so far:

$dates[] = array("date" => "2016-02-18 02:00:00", "duration" => "600");
$dates[] = array("date" => "2016-02-18 02:05:00", "duration" => "300");
$dates[] = array("date" => "2016-02-18 02:10:00", "duration" => "600");
$dates[] = array("date" => "2016-02-18 02:25:00", "duration" => "300");
$dates[] = array("date" => "2016-02-18 02:30:00", "duration" => "600");

$pickedDates = [];

function findMeetingAlreadyExistsInArray($array, $dateTime){
foreach($array as $item){
if ($item["date"] === $dateTime) return true;
}
}
function closestDate($dateArray, $compareDate, &$pickedDates = array()){
$dates = [];
foreach($dateArray as $key => $originalDate){
$date = $originalDate['date'];
if(!findMeetingAlreadyExistsInArray($pickedDates, $date)){
if(abs(strtotime($compareDate["date"]) - strtotime($date)) >= $compareDate["duration"]){
$dates[$key] = abs(strtotime($compareDate["date"]) - strtotime($date));
}
}
}
asort($dates);
$dateIndex = array_shift(array_keys($dates));
array_push($pickedDates, $dateArray[$dateIndex]);
return $dateArray[$dateIndex];
}
foreach($dates as $item) closestDate($dates, $item, $pickedDates);
print_r($pickedDates);


Result from above function:

Array
(
[0] => Array
(
[date] => 2016-02-18 02:10:00
[duration] => 600
)

[1] => Array
(
[date] => 2016-02-18 02:00:00
[duration] => 600
)

[2] => Array
(
[date] => 2016-02-18 02:25:00
[duration] => 300
)

[3] => Array
(
[date] => 2016-02-18 02:30:00
[duration] => 600
)

[4] => Array
(
[date] => 2016-02-18 02:05:00
[duration] => 300
)

)


Expected Result:

Array
(
[0] => Array
(
[date] => 2016-02-18 02:00:00
[duration] => 600
)
[1] => Array
(
[date] => 2016-02-18 02:10:00
[duration] => 600
)
[2] => Array
(
[date] => 2016-02-18 02:25:00
[duration] => 300
)
[3] => Array
(
[date] => 2016-02-18 02:30:00
[duration] => 600
)
)

Answer Source

Here is my attempt... I changed quite a bit just to wrap my head around exactly what you are trying to do.

$dates[] = array("date" => "2016-02-18 02:00:00", "duration" => "600"); // 10 mins
$dates[] = array("date" => "2016-02-18 02:05:00", "duration" => "300"); // 5 mins
$dates[] = array("date" => "2016-02-18 02:10:00", "duration" => "600");
$dates[] = array("date" => "2016-02-18 02:25:00", "duration" => "300");
$dates[] = array("date" => "2016-02-18 02:30:00", "duration" => "600");

$pickedDates = [];

function dateExists(array $array, $date) {
    if (empty($array)) {
        return false;
    }

    $flag = false;
    foreach($array as $value) {
        // exact match
        if ($value['date'] == $date) {
            return true;
        }

        // range match
        $start = strtotime($value['date']);
        $end = $start + $value['duration'];
        $ts = strtotime($date);
        if ($ts > $start && $ts < $end) {
            $flag = true;
            break;
        }
    }

    return $flag;
}

foreach ($dates as $key => $date) {
    if (!dateExists($pickedDates, $date['date'])) {
        $pickedDates[$key] = $date;
    }
}

echo '<pre>';
var_dump($pickedDates);
echo '</pre>';

This produces the desired results:

array(4) {
  [0]=>
  array(2) {
    ["date"]=>
    string(19) "2016-02-18 02:00:00"
    ["duration"]=>
    string(3) "600"
  }
  [2]=>
  array(2) {
    ["date"]=>
    string(19) "2016-02-18 02:10:00"
    ["duration"]=>
    string(3) "600"
  }
  [3]=>
  array(2) {
    ["date"]=>
    string(19) "2016-02-18 02:25:00"
    ["duration"]=>
    string(3) "300"
  }
  [4]=>
  array(2) {
    ["date"]=>
    string(19) "2016-02-18 02:30:00"
    ["duration"]=>
    string(3) "600"
  }
}

Not sure if your closestDate function has to exist and with those exact parameters. Either way, you should be able to modify this to suit your requirements.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download