PHP - 如何计算一个月或一年后

PHP - How to calculate one month or one year later

我想计算 PHP 中 Recurly 计划的下一个计费日期。 有两种计费周期:每年 |每月。 我尝试使用 DateTime 和 DateInterval 类,但没有得到预期的结果。

<?php
$referenceTime = new \DateTime('2016-01-31');
$oneMonthLater = $referenceTime->modify('+1 month');
var_dump($oneMonthLater);
// public 'date' => string '2016-03-02 00:00:00.000000'

在 1 月 31 日加一个月得到 3 月 2 日,而不是我预期的 2 月 29 日(或 28 日)。

8 月 31 日也一样:

<?php
$referenceTime = new \DateTime('2016-08-31');
$oneMonthLater = $referenceTime->modify('+1 month');
var_dump($oneMonthLater);
// public 'date' => string '2016-10-01 00:00:00.000000'

如果每年,我预计 2016 年 2 月 29 日 + 1 年 => 2017 年 2 月 28 日

谢谢。

可能是这样的:

if (date('d') !== date('d', strtotime('+1 month'))
    date ('Y-m-d H:i:s', strtotime('last day of next month'));

if (date('d') !== date('d', strtotime('+1 year'))
    date ('Y-m-d H:i:s', strtotime('last day of this month next year'));

您可以使用 PHP 的 DateTime 对象调用 modify 来计算相对于当前日期的下一个日期。以下代码显示了您将如何处理您的具体情况。

$next_bill_date = new DateTime();
switch($plan_interval_unit) {
    case "year":
        $next_bill_date->modify("last day of next month");
        break;

    case "month":
        $next_bill_date->modify("last day of this month next year");
        break;
}

试试这个,如果 date > 28 use last day of next month 否则使用 +1 month

$get_date = strtotime("31-01-2016");
$dt = explode("-",$get_date);
$dt = $dt[0];
var_dump(($dt > 28) ? date("d-m-Y", strtotime("31-01-2016 last day of next month")) : date("d-m-Y", strtotime("31-01-2016 +1 month")));

DEMO

您可以使用 PHP 内置 strtotime() 函数

// One month from today
$date = date('Y-m-d', strtotime('+1 month'));

// One month from a specific date
$date = date('Y-m-d', strtotime('+1 month', strtotime('2016-12-06')));
function get_next_billing_date($now, $type, $format = 'Y-m-d')
{
    $date = new DateTime($now);

    $y = $date->format("Y");
    $m = $date->format("m");
    $d = $date->format("d");

    if ($type == 'year') {
        $y++;
        if ($m == 2 && $d == 29) {
            $d = 28;
        }
    } else if ($type == 'month') {
        if ($m == 12) {
            $y++;
            $m = 1;
        } else {
            $m++;
        }

        $first_date = sprintf("%04d-%02d-01", $y, $m);
        $last_day_of_next_month = date('t', strtotime($first_date));

        if ($d > $last_day_of_next_month) {
            $d = $last_day_of_next_month;
        }
    } else {
        // not supported
        return false;
    }

    $date->setDate($y, $m, $d);

    return $date->format($format);
}