PHP->;由一周中的天数数组定义的下一个最近日期


PHP -> Next nearest date defined by array of days in week

真的需要帮助解决这个问题。

我有一系列offerDays-$offerDays = array(1,6);(平均周一和周六);

例如,输入日期为2014年9月3日星期三。下一个优惠日期是星期六2014/09/06

问题:如何在php中确定最近的第二天?类似的东西

$offerDays = array(1,6);
$inputDate = '2014/09/03'; // filled date, not actual date
$offerDate = findDate($inputDate, $offerDays); // returns 2014/09/06
function findDate($inputDate, $offerDays) {
return 'nearest next date to $inputDate defined by $offerDays';
}

这里可以有一个offerdays的变量数组。

$offerDays = array(1,6);
$inputDate = '2014/09/04'; // filled date, not actual date
$offerDate = findDate($inputDate, $offerDays);
function findDate($inputDate, $offerDays) {
   $date = DateTime::createFromFormat('Y/m/d', $inputDate);
   $num = $date->format('w');
   $min = 10; //initialize minimum days
   foreach($offerDays as $o){  //loop through all the offerdays to find the minimum difference
     $dif = $o - $num;
     if($dif>0 && $dif < $min){
        $min = $dif ;
       }
   }
   // if minimum days is not changed then get the first offerday from next week
   if($min == 10){
      $min = 6 - $num + min($offerDays);
   }
   //add the days till next offerday
   $add = new DateInterval('P'.$min.'D');
   $nextOfferDay = $date->add($add)->format('Y/m/d');
  return $nextOfferDay;
}
$currentDate = date('Y-m-d');
$frequencyDays = [2, 4, 5];
function nextNearestDate($currentDate, $frequencyDays) {
    $weekDay = date('w', strtotime($currentDate));
    $min = 10; // Some random number>7
    foreach ($frequencyDays as $day) {
        $dif = $day - $weekDay;
        if ($dif == 0) {
            $min = $dif;
            break;
        }else if ($dif > 0) {
            $positiveDay[] = $dif;
        }else if ($dif < 0) {
            $negativeDay[] = $dif;
        }
    }
    if ($min != 0) {
        if (isset($positiveDay) && count($positiveDay)) {
            $min = min($positiveDay);
        } else {
            $min = min($negativeDay);
            $min = 7 + $min;
        }
    }
    return $newDay = date('Y-m-d', strtotime('+' . $min . ' days', strtotime($currentDate)));
}
 $date_str="2014-09-03";
 if(date('l' , $date_str) != 'Saturday')
 {
     //Your Code Here
 }

简单版本

<?php
/**
 * Return the next date that falls on one of the specified weekdays.
 *
 * @param  DateTimeInterface $inputDate The search begins on the day after this
 * @param  array             $weekdays  An array of permitted weekdays
 *                                        represented by an integer (0=Sunday)
 *
 * @return DateTimeInterface|null  The first date that meets the criteria
 */
function findDate(DateTimeInterface $inputDate, array $weekdays)
{
    $weekdays = array_flip($weekdays);
    foreach (new DatePeriod($inputDate, new DateInterval('P1D'), 7, DatePeriod::EXCLUDE_START_DATE) as $possibleDate)
    {
        if (isset($weekdays[$possibleDate->format('w')]) === true)
        {
            return $possibleDate;
        }
    }
}
// Example:
$weekdays = [1, 6];
$inputDate = '2014/09/03';
$offerDate = findDate(new DateTimeImmutable($inputDate), $weekdays);
echo $offerDate->format('Y-m-d'), "'n";

扩展版本

如果你想通过建立一个稍微抽象一点的基础来解决这个问题,它可能看起来像:

<?php
function WeekDayIterator(DateTimeInterface $inputDate, array $weekdays)
{
    $weekdays = array_intersect($weekdays, range(0,6));
    if (!$weekdays)
    {
        return;
    }
    $possibleDate = new DateTimeImmutable('@' . $inputDate->getTimeStamp());
    $oneDay = new DateInterval('P1D');
    $weekdays = array_flip($weekdays);
    while (true)
    {
        $possibleDate = $possibleDate->add($oneDay);
        if (isset($weekdays[$possibleDate->format('w')]) === true)
        {
            yield $possibleDate;
        }
    }
}
function findDate(DateTimeInterface $inputDate, array $weekdays)
{
    return WeekDayIterator($inputDate, $weekdays)->current();
}
// Example:
$weekdays = [1, 6];
$inputDate = '2014/09/03';
$offerDate = findDate(new DateTimeImmutable($inputDate), $weekdays);
echo $offerDate->format('Y-m-d'), "'n";
foreach (new LimitIterator(WeekDayIterator(new DateTimeImmutable($inputDate), $weekdays), 0, 10) as $date)
{
    echo $date->format('Y-m-d (w)'), "'n";
}

这个较长的版本为您提供了一个迭代器,它将在所有有效日期上无限循环。findDate方法现在只是一种隐藏实现细节的方便方法。

但这里的优点是,您现在可以解决类似的问题,而不必编写更多的管道。例如,您可以使用LimitIterator计算接下来的10个日期。(也许你想提供可用日期的下拉列表等)

第二个版本在很大程度上依赖于5.5,但第一个版本不是(如果将DateTimeImmutable替换为DateTime)。