我想弄清楚如何计算经常性某个特定日期之后的最近日期。
例如,如果经常性周期是每两周一次,从2016年1月1日开始,给定日期是1月17日,我如何计算下一个经常性日期是1月28日?
经常性的时期可以是任意天数,数周,数月或数年。
现在我能想到的唯一解决方案是从开始日期和循环开始,在每次迭代中添加重复周期,直到我通过给定日期,但我想知道是否有更高效或更优雅的解决方案?
答案 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);
]
];