Carbon::diffInDays
Returns the number of days between two dates as a signed float.
public function diffInDays($date = null, bool $absolute = false, bool $utc = false): float- Added in Laravel Carbon 1.0
Parameters
| Parameter | Type | Description |
|---|---|---|
$$dateoptional | Carbon|DateTimeInterface|string|null= null | The date to compare against. Null compares against the current moment. Strings are run through Carbon's parser. |
$$absoluteoptional | bool= false | Return the magnitude with the sign removed. |
$$utcoptional | bool= false | Convert both dates to UTC before comparing, so daylight-saving shifts do not alter the count. |
Return value
floatThe difference in days as a float, negative when the compared date is earlier than the instance, unless $absolute is true.
Errors
Throws Carbon\Exceptions\InvalidFormatException when a string argument cannot be parsed.
Changelog
- PHP 3.0Returns a float instead of an int, and $absolute now defaults to false. In Carbon 2 the signature was diffInDays($date = null, $absolute = true) and the result was a truncated positive integer. Restore the old behaviour with (int) $a->diffInDays($b, true).
diffInDays() measures the gap between two dates in days. Under Carbon 3 it returns a signed float: $a->diffInDays($b) is positive when $b comes after $a, negative when it comes before, and it carries the fractional part of the day.
The Carbon 2 difference
This is the upgrade that breaks quietly. Carbon 2 defaulted $absolute to true and returned a truncated int, so code written as if ($start->diffInDays($end) > 30) compared a positive whole number. The same line under Carbon 3 can compare a negative float and take the wrong branch. Pass absolute: true to restore the magnitude, and cast to int when you want the old truncation.
Fractions surprise people
Two dates one calendar day apart differ by 1.0 only if their times of day match. From 15:00 yesterday to 09:00 today the answer is roughly 0.75, and casting that to int gives 0 — the classic "why does it say zero days" bug. When you mean calendar days, call startOfDay() on both sides first.
Set $utc to true when a daylight-saving change sits inside the range and you want exact 24-hour days.
Example
When to use it
- Counting how many days remain before a subscription renews.
- Bucketing records by age in days for a retention report.
- Deciding whether a stored value is older than a fixed threshold.
Frequently asked questions
Why does diffInDays return a negative number now?
Carbon 3 changed $absolute to default to false, so the result is signed — negative when the compared date is earlier than the instance. Pass absolute: true to get the Carbon 2 magnitude back.
Why do I get a float like 12.778 instead of 12?
Carbon 3 returns the exact difference including the fraction of a day, where Carbon 2 truncated to an int. Cast with (int) for truncation, use round() or ceil() for other rounding, or call startOfDay() on both dates when you want whole calendar days.
How do I count calendar days between two dates?
Normalise both sides first: $a->copy()->startOfDay()->diffInDays($b->copy()->startOfDay(), absolute: true). Comparing the raw instances measures elapsed time, so two dates on different days can differ by less than one.
More examples
Whole calendar days, not elapsed time
The two dates fall on different calendar days but are only eighteen hours apart, so the raw difference truncates to zero. Zeroing the time on both sides is what turns the question into 'how many date boundaries were crossed'.
<?php
use Carbon\Carbon;
$start = Carbon::parse('2026-03-13 15:00:00');
$end = Carbon::parse('2026-03-14 09:00:00');
var_dump($start->diffInDays($end)); // float(0.75)
var_dump((int) $start->diffInDays($end)); // int(0)
var_dump($start->copy()->startOfDay()->diffInDays($end->copy()->startOfDay())); // float(1)A retention bucket on a model
Leaving $absolute at its default keeps the sign meaningful: once the trial end passes, the value goes negative and max() clamps it to zero. ceil() reports a partial day as a full remaining day, which is what a countdown should show.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Account extends Model
{
protected function casts(): array
{
return ['trial_ends_at' => 'datetime'];
}
public function daysLeftInTrial(): int
{
if ($this->trial_ends_at === null) {
return 0;
}
// Positive while the end date is still in the future.
return max(0, (int) ceil(now()->diffInDays($this->trial_ends_at)));
}
}Surviving a daylight-saving boundary
The clocks go forward between these two dates, so only 47 real hours elapse. The default answer counts calendar days and says 2; passing utc: true measures actual elapsed time instead.
<?php
use Carbon\Carbon;
$start = Carbon::parse('2026-03-28 12:00', 'Europe/London');
$end = Carbon::parse('2026-03-30 12:00', 'Europe/London');
var_dump($start->diffInDays($end)); // float(2)
var_dump($start->diffInDays($end, utc: true)); // float(1.9583333333333333)
Discussion