Carbon::endOfMonth
Moves a Carbon instance to the last day of its month at 23:59:59.999999.
public function endOfMonth(): static- Added in Laravel Carbon 1.0
Return value
staticThe same instance moved to the last day of its month with the time set to 23:59:59.999999 ($this for the mutable Carbon class, a new instance for CarbonImmutable).
Changelog
- PHP 2.0The time component is set to 23:59:59.999999 rather than 23:59:59, so a value formatted through toDateTimeString() loses the microseconds it carries.
endOfMonth() jumps to the final day of the instance's month and sets the time to 23:59:59.999999. It reads the month's real length, so February gives the 28th or the 29th and leap years need no special case — which is the whole reason to prefer it over hand-rolled arithmetic.
The microsecond trap
The instance carries 999999 microseconds, but toDateTimeString() prints only 23:59:59. That mismatch is where bugs come from: a whereBetween against a column stored with second precision can drop rows in the final second, and a comparison against a value read back from the database fails an equality check it visibly should pass. For range queries, use the start of the next month with a strict < instead — $date->copy()->startOfMonth()->addMonth().
It mutates
The mutable Carbon class rewrites the instance and returns it, so calling this on a model attribute changes that attribute. Reach for copy(), or CarbonImmutable, when the original date must survive.
The family
endOfDay(), endOfWeek(), endOfQuarter() and endOfYear() behave identically, as does the generic endOf('month'). lastOfMonth() is different: it lands on the last day at 00:00:00, or on the last given weekday of the month.
Example
When to use it
- Setting the upper bound of a monthly billing or reporting period.
- Finding the last day of February without special-casing leap years.
- Filling a due-date field that should fall at the very end of the month.
Frequently asked questions
How do I get the last day of a month?
Call ->endOfMonth() on any date in that month; Carbon reads the month's real length, so February resolves to the 28th or 29th automatically. Use ->lastOfMonth() when you want that date at midnight instead of at 23:59:59.999999.
Why does my whereBetween miss rows on the last day?
Because endOfMonth() carries 999999 microseconds that a second-precision column cannot store, so rows written in the final second can fall outside the range. Use the start of the next month with a strict less-than comparison instead.
Does endOfMonth change the original instance?
Yes on the mutable Carbon and Illuminate\Support\Carbon classes — it rewrites the instance and returns it. Call ->copy() first, or use CarbonImmutable, when the starting date must be preserved.
More examples
A billing period without the microsecond risk
A half-open range covers the whole month including its final second, which a whereBetween against 23:59:59.999999 can miss on a second-precision column. startOfMonth()->addMonth() never overflows, because the first of a month exists in every month.
<?php
use App\Models\Charge;
use Carbon\Carbon;
$anchor = Carbon::parse('2026-02-14');
$start = $anchor->copy()->startOfMonth();
$next = $start->copy()->addMonth();
$total = Charge::query()
->where('charged_at', '>=', $start)
->where('charged_at', '<', $next)
->sum('amount');
echo $start->toDateTimeString(), ' -> ', $next->toDateTimeString(), PHP_EOL;
// 2026-02-01 00:00:00 -> 2026-03-01 00:00:00Month lengths handled for you
The leap year is resolved from the actual calendar rather than a modulo rule, so 2024 and 2026 differ without any branching. daysInMonth exposes the same number if you need the count itself.
<?php
use Carbon\Carbon;
foreach (['2026-01-05', '2026-02-05', '2024-02-05', '2026-04-05'] as $input) {
$end = Carbon::parse($input)->endOfMonth();
echo $input, ' -> ', $end->toDateString(), ' (', $end->daysInMonth, " days)\n";
}
// 2026-01-05 -> 2026-01-31 (31 days)
// 2026-02-05 -> 2026-02-28 (28 days)
// 2024-02-05 -> 2024-02-29 (29 days)
// 2026-04-05 -> 2026-04-30 (30 days)endOfMonth versus lastOfMonth
endOfMonth() is a boundary and keeps the very end of the day, while lastOfMonth() is a date and starts it at midnight. Passing a weekday to lastOfMonth() finds the last Friday of the month, which endOfMonth() cannot express.
<?php
use Carbon\Carbon;
$date = Carbon::parse('2026-03-14');
echo $date->copy()->endOfMonth()->toDateTimeString(), "\n";
// 2026-03-31 23:59:59
echo $date->copy()->lastOfMonth()->toDateTimeString(), "\n";
// 2026-03-31 00:00:00
echo $date->copy()->lastOfMonth(Carbon::FRIDAY)->toDateString(), "\n";
// 2026-03-27
Discussion