1
votes

I'd like to calculate next billing date of Recurly plan in PHP. There are 2 types of billing cycle: yearly | monthly. I tried to use DateTime and DateInterval classes, but didn't get expected results.

<?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'

Adding one month to the 31st of Januray gives me the second of March and not the 29th (or 28th) of February as I would expect.

The same for the 31st of August:

<?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'

If yearly, I expect Feb 29, 2016 + 1 year => Feb 28, 2017

Thanks.

5
Show us what you have done so far... It will be easier for us to answer.d.coder
$next_bill_date = new DateTime(); if ($plan_interval_unit == 'year') { $interval_spec = 'P'.$plan['plan_interval_length'].'Y'; } else if ($plan_interval_unit == 'month') { $interval_spec = 'P'.$plan['plan_interval_length'].'M'; } $next_bill_date->add(new DateInterval($interval_spec));Paul Z.
Add it in your question please. Hard to read/understand here... :(d.coder

5 Answers

2
votes

Try this, if date > 28 use last day of next month else use +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

1
votes

You can call modify with PHP's DateTime object to calculate the next date relative to the current date. The following code shows how you would do it with your specific situation.

$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;
}
0
votes

May be something like that:

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'));
0
votes

You can use PHP inbuilt strtotime() function

// 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')));
0
votes
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);
}