使用一个已经选择的日期:测试示例
$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");
$alreadyChosenDates[] = array("date" => "2016-02-18 02:10:30", "duration" => "600"); // 10 mins
//$alreadyChosenDates[] = array("date" => "2016-02-18 02:05:00", "duration" => "300"); // 5 mins
function returnClosestTime($alreadyChosenDates, $dates){
// Set an array called $closestTime that has the time difference and the key
$closestTime = [null, null];
// Check each element in array
foreach($dates as $key => $date){
foreach($alreadyChosenDates as $chosenDates){
// Calculate difference between already chosen dates array and the dates array
$diff = (strtotime($chosenDates["date"]) + $chosenDates["duration"]) - strtotime($date["date"]);
if($diff < 0) $diff = $diff * -1;
// If $closestTime is empty, populate it
if($closestTime[0] === null) $closestTime = [$diff, $key];
// If $closestTime isn't empty and the current date's time difference
// is smaller, populate $closestTime with the time difference and key
else if($diff < $closestTime[0]) $closestTime = [$diff, $key];
}
}
return $dates[$closestTime[1]];
}
echo "<pre>";
print_r(returnClosestTime($alreadyChosenDates, $dates));
echo "</pre>";
输出:Array
(
[date] => 2016-02-18 02:25:00
[duration] => 300
)
在上面的例子中,我只使用一个已经选择的日期,但我正在寻找一些帮助,我如何使用两个已经选择的日期?
所以不只是这样:
$alreadyChosenDates[] = array("date" => "2016-02-18 02:10:30", "duration" => "600"); // 10 mins
应该是这个
$alreadyChosenDates[] = array("date" => "2016-02-18 02:10:30", "duration" => "600"); // 10 mins
$alreadyChosenDates[] = array("date" => "2016-02-18 02:05:00", "duration" => "300"); // 5 mins
和最接近的日期/时间将最接近2016-02-18 02:10:30
或2016-02-18 02:05:00
,但如果最接近的时间将在2016-02-18 02:10:30
和2016-02-18 02:05:00
的中间也会很好。
我该怎么做呢?
我不知道您是否喜欢OOP方法,但是您可以使用这个类:
class ClosestIndicationFinder
{
protected $indications;
protected $chosenIndications;
public function __construct(
array $indications,
array $chosenIndications = null
) {
$this->indications = $indications;
$this->chosenIndications = $chosenIndications;
}
public function setChosenIndications(array $chosenIndications)
{
$this->chosenIndications = $chosenIndications;
return $this;
}
public function addChosenIndication($indication)
{
$this->chosenIndications[] = $indication;
return $this;
}
public function findClosestIndication()
{
$this->findAverageChosenIndicationTimestamp();
$this->findAbsoluteIndicationDifferences();
return $this->findClosestsIndicationBasedOnDiffs();
}
protected $averageChosenTimestamp;
protected function findAverageChosenIndicationTimestamp()
{
$sum = array_reduce(
$this->chosenIndications,
function ($sum, $indication) {
return $sum + $this->calculateIndicationEndTimestamp($indication);
},
0
);
$this->averageChosenTimestamp = (int) $sum / count($this->chosenIndications);
}
protected $diffs;
protected function findAbsoluteIndicationDifferences()
{
$this->diffs = array_map(function ($indication) {
return abs($this->calculateIndicationsDifference(
$indication,
$this->averageChosenTimestamp
));
}, $this->indications);
}
protected function calculateIndicationsDifference($indication1, $indication2)
{
$timestamp1 = is_array($indication1)
? $this->calculateIndicationBeginningTimestamp($indication1)
: $indication1;
$timestamp2 = is_array($indication2)
? $this->calculateIndicationEndTimestamp($indication2)
: $indication2;
return $timestamp1 - $timestamp2;
}
protected function calculateIndicationBeginningTimestamp(array $indication)
{
return strtotime($indication['date']);
}
protected function calculateIndicationEndTimestamp(array $indication)
{
return strtotime($indication['date']) + $indication['duration'];
}
protected function findClosestsIndicationBasedOnDiffs()
{
$closestIndicationIndex = array_search(min($this->diffs), $this->diffs);
if (!isset($this->indications[$closestIndicationIndex])) {
return null;
}
return $this->indications[$closestIndicationIndex];
}
}
我尝试让方法自描述,所以代码中没有注释。 OOP方法可以通过扩展类和只重写那些行为应该改变的方法来调整逻辑。例如,我看到你的另一个问题,你想要添加一个新选择的日期到选定的数组。在类中也有一个方法,但是,我将从初始日期数组中删除所选日期。但是由于我只知道最终任务,所以我很难使解决方案与初始任务紧密匹配。
对于多次选择的时间。你已经写了,但是看看最近的时间是否在中间也会很好。如果我错了,请纠正我,但是,如果你想要的日期,位于最接近所选日期的两个日期的中间,你可以计算所选日期的平均值并减少任务,只找到一个最接近的日期。
再说一遍,如果你能知道你在做什么,解决方案就能更准确。