Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

fredmarks's avatar

How to get carbon to return only a future date

I am working on recurring invoices, that recur every month.

I have a parent invoice which is used to generate new child invoices every month.

In the parent invoice, I keep track of the last recurring cycle date using a field last_renewed

This sounds simple enough to just use ->addMonth() on last_renewed to determin the next renewal date

HOWEVER

I also have a feature to allow pausing of the recurring cycle. Now, if the recurring is resumed after some months have passed, how can I get carbon to return a sure future next cycle date, based off the last_renewed date (which could now be, 4 months ago (e.g. 25 January 2020))

Using addMonth() or modify('next month') on last_renewed date, will return 25 February 2020. What i really want is 25 May 2020

0 likes
6 replies
MichalOravec's avatar

@fredmarks What about this. You add month to last_renewed date if it's not in future you just add month to actual date, in else part just return date base on last_renewed date + 30 days.

use Carbon\Carbon;

$date = Carbon::parse('2020-01-23'); // this will be your last_renewed from DB

$date->addMonth();

if ($date->lessThan(Carbon::now())) {
    echo Carbon::now()->addMonth();
} else {
    echo $date;
}
fredmarks's avatar

@michaloravec Thanks for the reply

I need the new future date to fall on same day as it would have been, had the cycle not been paused

i.e. 2020-01-23 should become 2020-05-23

If I used now() I will end up with 2020-05-25 (e.g. based on todays date 25th April)

MichalOravec's avatar
Level 75

@fredmarks This should work

use Carbon\Carbon;

$date = Carbon::parse('2020-01-23'); // this will be your last_renewed from DB

$date->addMonth();

if ($date->lessThan(Carbon::now())) {
    echo Carbon::now()->addMonth()->setDay($date->day);
} else {
    echo $date;
}
1 like
Snapey's avatar

do you care what date you resume on? So if the original billing date was 26th Feb and today is 25th April, is is ok to resume with only 1 day remaining?

I'm thinking you want the day of the month from the last invoice (eg 26), then you want the next 26th ?

Snapey's avatar

function resumeDate($last)
{
  
    $dayOfMonth = Carbon\Carbon::parse($last)->day;

    $next = now()->setDay($dayOfMonth);

    if($next < now()){
      $next->addMonth();
    }

    return $next;
}


echo (resumeDate('2020-01-31').PHP_EOL);
echo (resumeDate('2020-02-05').PHP_EOL);
echo (resumeDate('2020-02-25').PHP_EOL);
echo (resumeDate('2020-02-26').PHP_EOL);


2020-05-01 21:08:44
2020-05-05 21:08:44
2020-05-25 21:08:44
2020-04-26 21:08:44

You will notice an anomaly in the first result, as there is no 31st in April

Please or to participate in this conversation.