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

amitsolanki24_'s avatar

Get previous months from Carbon

CASE 1 :

    Carbon::now()->subDay()->subMonths(1)->format('M d, Y H:i:s a'),
    Carbon::now()->subDay()->subMonths(2)->format('M d, Y H:i:s a'), 
    Carbon::now()->subDay()->subMonths(3)->format('M d, Y H:i:s a'),
    Carbon::now()->subDay()->subMonths(4)->format('M d, Y H:i:s a')

When I use above code I got this output which is correct

"Jun 30, 2024 12:18:11 pm"
"May 30, 2024 12:18:11 pm"
"Apr 30, 2024 12:18:11 pm"
"Mar 30, 2024 12:18:11 pm"

CASE 2:

but when I use current date

    Carbon::now()->subMonths(1)->format('M d, Y H:i:s a'),
    Carbon::now()->subMonths(2)->format('M d, Y H:i:s a'), 
    Carbon::now()->subMonths(3)->format('M d, Y H:i:s a'),
    Carbon::now()->subMonths(4)->format('M d, Y H:i:s a')

then I got unexpected output

"Jul 01, 2024 12:22:10 pm"
"May 31, 2024 12:22:10 pm"
"May 01, 2024 12:22:10 pm"
"Mar 31, 2024 12:22:10 pm"
Note: In case 1 current date is 30th July, 2024 and in case 2 the current date is 31st July 2024, this is happing because of 31st ```

Any idea how can I get correct output.

Thanks in advance.
0 likes
6 replies
JussiMannisto's avatar

July has 31 days, June has 30. Calling subMonths(1) on July 31st results in June 31st, which rolls over to July 1st.

You can use the first day of the month before adding or subtracting months:

// 2024-06-01
$first = Carbon::now()->firstOfMonth()->subMonths(1)->format('Y-m-d');

// 2024-06-30
$last = Carbon::now()->firstOfMonth()->subMonths(1)->lastOfMonth()->format('Y-m-d');

// Or just get the last day with format():
$last = Carbon::now()->firstOfMonth()->subMonths(1)->format('Y-m-t');
1 like
puklipo's avatar

A common Carbon trap.

Use NoOverflow

Carbon::now()->subMonthsNoOverflow(1)->format('M d, Y H:i:s a');

or use settings() per instance.

$d = Carbon::now();
$d->settings([
    'monthOverflow' => false,
]);
$d = $d->subMonths(1)->format('M d, Y H:i:s a');

The global useMonthsOverflow is now deprecated.

Carbon::useMonthsOverflow(false);
1 like
amitsolanki24_'s avatar

I have fixed this issue by subtracting one day when the current date is 31.

	$currentDate = Carbon::now();
    $currentDay = $currentDate->copy()->format('d');

    // when current date is 31st

    if($currentDay == "31") {
        $currentDate->subDay();
    }

    $month1 = $currentDate->copy()->subMonths(1)->format('F');
    $month2 = $currentDate->copy()->subMonths(2)->format('F');
    $month3 = $currentDate->copy()->subMonths(3)->format('F');
    $month4 = $currentDate->copy()->subMonths(4)->format('F');

Please or to participate in this conversation.