如何在给定日期(PHP)之后计算经常性周期的最近日期

时间:2016-05-27 11:12:44

标签: php date

我想弄清楚如何计算经常性某个特定日期之后的最近日期。

例如,如果经常性周期是每两周一次,从2016年1月1日开始,给定日期是1月17日,我如何计算下一个经常性日期是1月28日?

经常性的时期可以是任意天数,数周,数月或数年。

现在我能想到的唯一解决方案是从开始日期和循环开始,在每次迭代中添加重复周期,直到我通过给定日期,但我想知道是否有更高效或更优雅的解决方案?

7 个答案:

答案 0 :(得分:4)

您可以使用DatePeriod来完成它:

$begin = new DateTime('2016-01-01');
$end = new DateTime('2016-12-31');
$interval = new DateInterval('P14D');
$datePeriod = new DatePeriod($begin, $interval ,$end);

$givenDate = new DateTime('2016-01-17');

foreach ($datePeriod as $date) {
    if ($date < $givenDate) {
        continue;
    }

    echo 'The next recurring period date is ' . $date->format('Y-m-d');
    break;
}

输出结果为:

  

下一个经常性日期为2016-01-29

答案 1 :(得分:0)

如果你是开放的并且不介意数据库选项和迷你cron脚本,我有一个建议。创建一个名为recurring_track的表,并具有键值列:

例如:

last_recurring_period作为键,值为05-25-2016

现在运行一个cron脚本,每次重复出现持续时间时都会更新它。

现在您只需要查询此表以确定最后一个周期时间,以及现在何时将是您可以添加和确定的给定日期的下一个周期时间。

答案 2 :(得分:0)

试试这个,

    $starting_dat = '2016-01-01';
    $recurring_prd = "2 week";
    $given_dat = '2016-02-28';

    while ($given_dat > $starting_dat)
    {


            $next_date=date('Y-m-d', strtotime($recurring_prd, strtotime(date($starting_dat))));
            $starting_dat = $next_date;
    }

    echo date('d-m-Y', strtotime($next_date));

答案 3 :(得分:0)

 $now = time(); // or your date as well
 $your_date = strtotime("2010-01-01");

 //Get difference in days  
 $datediff = $now - $your_date; // in days say 60 days 

 //use mod with your reoccurring period 
 $remain = $datediff % $recPeriod // her say 2 weeks = 14 days recurring gets you 4
 //nearest recured date 
 $recdate = strtotime("-".$remain." day", $now); // 4 days ago 

Modify similar way for next date too

答案 4 :(得分:0)

除了循环,你可以只做一些数学运算并利用DateTime类:

$start = new DateTime("2016-01-01");
$interval = 14;

$current = new DateTime("2016-01-17");

// Here we subtract from the interval (14 days) the amount of days remaining
// to the next recurring date
$daysUntilNext = $interval - ($current->diff($start)->days % $interval);

$next = $current->modify("+$daysUntilNext days");

// $next now contains the next recurring date

答案 5 :(得分:0)

另一种看法,与@Matei Mihai的相似,但不需要在最后一个循环中进行检查。感觉应该有更好的方法将DateInterval的多个实例添加到DateTime。

<?php
$start   = new DateTime('2016-01-01');
$cutOff  = new DateTime('2016-01-17');
$period  = new DateInterval('P2W');

// Find out the total number of complete periods between the two dates
$distance = $start->diff($cutOff)->days;
$periodsBetween = (int) ($distance / $period->d);

// Then add on that number of periods + 1 to the original date
for ($a=1; $a<=$periodsBetween + 1; $a++)
{
    $start->add($period);
}

echo $start->format('Y-m-d'); // 2016-01-29

答案 6 :(得分:0)

我在下面使用Carbon简化了阅读方式,但是我最近需要在一个项目上进行此操作,因此在网上找不到很多东西。这是我想出的解决方案:

    <?php
    $arr = [
        'type' => 'days', // any unit of measure - months, years, seconds, etc.
        'units' => 20 // length of each period in the above type. E.g. 20 days
    ];


    /** 
     *  -------------------------------------------------------
     * | Begin calculating time remaining in the current cycle.|
     *  -------------------------------------------------------
     */


    /**
     * When the cycle intervals originally started
     * Throwing a random date here but could be whatever you want.
     */
    $startDate = Carbon::now()->subDays(300);

    /**
     * Total number of units since start date
     */
    $diffMethodUnit = ucfirst($arr['type']);
    $diffMethod = "floatDiffIn{$diffMethodUnit}";
    $totalLapsed = $startDate->{$diffMethod}();

    /**
     * Get the start date of the current cycle
     */
    $currentStartDate = $startDate->add(floor($totalLapsed), $arr['type']);

    /**
     * This gives us how many of the unit has lapsed 
     * since the beginning of the current cycle
     */
    $currentLapsed = $totalLapsed - floor($totalLapsed);

    /**
     * Finally, get the end date of the current cycle
     */
    $currentEndDate = Carbon::now()
        ->sub($arr['type'], $currentLapsed)
        ->add($arr['type'], $arr['units']);

    $arr['current_cycle'] = [
        'start' => $currentStartDate;
        'end' => $currentEndDate;
        'remaining' => [
             'seconds' => Carbon::now()->diffInSeconds($currentEndDate);
             'minutes' => Carbon::now()->diffInMinutes($currentEndDate);
             'hours' => Carbon::now()->diffInHours($currentEndDate);
             'days' => Carbon::now()->diffInDays($currentEndDate);
             'weeks' => Carbon::now()->diffInWeeks($currentEndDate);
             'months' => Carbon::now()->diffInMonths($currentEndDate);
             'years' => Carbon::now()->diffInYears($currentEndDate);
        ]
     ];