Difference
Carbon diff() and diffAsCarbonInterval() methods return a CarbonInterval (since Carbon v3, while it returned DateInterval in the previous versions).
Check CarbonInterval chapter for more information.
We also provide diffAsDateInterval() act like diff() but returns a DateInterval instance.
Carbon add diff methods for each unit too, such as diffInYears(), diffInMonths() and so on. diffAsCarbonInterval() and diffIn*() (and floatDiffIn*() for versions < 3 when diffIn*() methods returned integer values, since Carbon 3, they are deprecated as diffIn*() already return floating number, and integer values from it can easily be obtained with an explicit cast (int)).
diffInUnit() allow to get a diff for a unit calculated dynamically: ->diffInUnit($unit, $date, $absolute)
All can take 2 optional arguments: date to compare with (if missing, now is used instead), and an absolute boolean option (false by default), it returns negative value when the instance the method is called on is greater than the compared date (first argument or now). If set to true, that makes the method return an absolute value no matter which date is greater than the other.
echo Carbon::now('America/Vancouver')->diffInSeconds(Carbon::now('Europe/London')); // 3.1E-5
$dtOttawa = Carbon::createMidnightDate(2000, 1, 1, 'America/Toronto');
$dtVancouver = Carbon::createMidnightDate(2000, 1, 1, 'America/Vancouver');
echo $dtOttawa->diffInHours($dtVancouver); // 3
echo $dtVancouver->diffInHours($dtOttawa); // -3
echo $dtOttawa->diffInHours($dtVancouver, false); // 3
echo $dtVancouver->diffInHours($dtOttawa, false); // -3
$dt = Carbon::createMidnightDate(2012, 1, 31);
echo $dt->diffInDays($dt->copy()->addMonth()); // 31
echo $dt->diffInDays($dt->copy()->subMonth(), false); // -31
$dt = Carbon::createMidnightDate(2012, 4, 30);
echo $dt->diffInDays($dt->copy()->addMonth()); // 30
echo $dt->diffInDays($dt->copy()->addWeek()); // 7
$dt = Carbon::createMidnightDate(2012, 1, 1);
echo $dt->diffInMinutes($dt->copy()->addSeconds(59)); // 0.98333333333333
echo $dt->diffInMinutes($dt->copy()->addSeconds(60)); // 1
echo $dt->diffInMinutes($dt->copy()->addSeconds(119)); // 1.9833333333333
echo $dt->diffInMinutes($dt->copy()->addSeconds(120)); // 2
echo $dt->addSeconds(120)->secondsSinceMidnight(); // 120
$interval = $dt->diffAsCarbonInterval($dt->copy()->subYears(3), false);
// diffAsCarbonInterval use same arguments as diff($other, $absolute)
// (native method from \DateTime)
// except $absolute is true by default for diffAsCarbonInterval and false for diff
// $absolute parameter allow to get signed value if false, or always positive if true
echo ($interval->invert ? 'minus ' : 'plus ') . $interval->years; // minus 3These methods have int-truncated results. That means diffInMinutes returns 1 for any difference between 1 included and 2 excluded. But same methods are available for float results:
echo Carbon::parse('06:01:23.252987')->floatDiffInSeconds('06:02:34.321450'); // 71.068463
echo Carbon::parse('06:01:23')->floatDiffInMinutes('06:02:34'); // 1.1833333333333
echo Carbon::parse('06:01:23')->floatDiffInHours('06:02:34'); // 0.019722222222222
// Those methods are absolute by default but can return negative value
// setting the second argument to false when start date is greater than end date
echo Carbon::parse('12:01:23')->floatDiffInHours('06:02:34', false); // -5.9802777777778
echo Carbon::parse('2000-01-01 12:00')->floatDiffInDays('2000-02-11 06:00'); // 40.75
echo Carbon::parse('2000-01-01')->floatDiffInWeeks('2000-02-11'); // 5.8571428571429
echo Carbon::parse('2000-01-15')->floatDiffInMonths('2000-02-24'); // 1.3103448275862
// floatDiffInMonths count as many full months as possible from the start date
// (for instance 31 days if the start is in January), then consider the number
// of days in the months for ending chunks to reach the end date.
// So the following result (ending with 24 march is different from previous one with 24 february):
echo Carbon::parse('2000-02-15 12:00')->floatDiffInMonths('2000-03-24 06:00'); // 1.2822580645161
// floatDiffInYears apply the same logic (and so different results with leap years)
echo Carbon::parse('2000-02-15 12:00')->floatDiffInYears('2010-03-24 06:00'); // 10.100684931507WARNING
Important note about the daylight saving times (DST), by default PHP DateTime does not take DST into account, that means for example that a day with only 23 hours like March the 30th 2014 in London will be counted as 24 hours long.
WARNING
Be careful of floatDiffInMonths() which can gives you a lower result (number of months in A < number of months in B) for an interval having more days (number of days in A > number of days in B) due to the variable number of days in months (especially February). By default, we rely on the result of DateTime::diff which is sensitive to overflow. See issue #2264 for alternative calculations.
$date = new \DateTime('2014-03-30 00:00:00', new \DateTimeZone('Europe/London')); // DST off
echo $date->modify('+25 hours')->format('H:i'); // 01:00 // (DST on, 24 hours only have been actually added)Carbon follow this behavior too for add/sub/diff seconds/minutes/hours. But we provide methods to works with real hours using timestamp:
$date = new Carbon('2014-03-30 00:00:00', 'Europe/London'); // DST off
echo $date->addRealHours(25)->format('H:i'); // 02:00 // (DST on)
echo $date->diffInRealHours('2014-03-30 00:00:00'); // -25
echo $date->diffInHours('2014-03-30 00:00:00'); // -25
echo $date->diffInRealMinutes('2014-03-30 00:00:00'); // -1500
echo $date->diffInMinutes('2014-03-30 00:00:00'); // -1500
echo $date->diffInRealSeconds('2014-03-30 00:00:00'); // -90000
echo $date->diffInSeconds('2014-03-30 00:00:00'); // -90000
echo $date->diffInRealMilliseconds('2014-03-30 00:00:00'); // -90000000
echo $date->diffInMilliseconds('2014-03-30 00:00:00'); // -90000000
echo $date->diffInRealMicroseconds('2014-03-30 00:00:00'); // -90000000000
echo $date->diffInMicroseconds('2014-03-30 00:00:00'); // -90000000000
echo $date->subRealHours(25)->format('H:i'); // 00:00 // (DST off)
// with float diff:
$date = new Carbon('2019-10-27 00:00:00', 'Europe/Paris');
echo $date->floatDiffInRealHours('2019-10-28 12:30:00'); // 37.5
echo $date->floatDiffInHours('2019-10-28 12:30:00'); // 37.5
echo $date->floatDiffInRealMinutes('2019-10-28 12:00:30'); // 2220.5
echo $date->floatDiffInMinutes('2019-10-28 12:00:30'); // 2220.5
echo $date->floatDiffInRealSeconds('2019-10-28 12:00:00.5'); // 133200.5
echo $date->floatDiffInSeconds('2019-10-28 12:00:00.5'); // 133200.5
// above day unit, "real" will affect the decimal part based on hours and smaller units
echo $date->floatDiffInRealDays('2019-10-28 12:30:00'); // 1.5625
echo $date->floatDiffInDays('2019-10-28 12:30:00'); // 1.5208333333333
echo $date->floatDiffInRealWeeks('2019-10-28 12:30:00'); // 0.22321428571429
echo $date->floatDiffInWeeks('2019-10-28 12:30:00'); // 0.2172619047619
echo $date->floatDiffInRealMonths('2019-10-28 12:30:00'); // 0.050403225806452
echo $date->floatDiffInMonths('2019-10-28 12:30:00'); // 0.049059139784946
echo $date->floatDiffInRealYears('2019-10-28 12:30:00'); // 0.0042691256830601
echo $date->floatDiffInYears('2019-10-28 12:30:00'); // 0.0041552823315118The same way you can use addRealX() and subRealX() on any unit.
There are also special filter functions diffInDaysFiltered(), diffInHoursFiltered() and diffFiltered(), to help you filter the difference by days, hours or a custom interval. For example to count the weekend days between two instances:
$dt = Carbon::create(2014, 1, 1);
$dt2 = Carbon::create(2014, 12, 31);
$daysForExtraCoding = $dt->diffInDaysFiltered(function(Carbon $date) {
return $date->isWeekend();
}, $dt2);
echo $daysForExtraCoding; // 104
$dt = Carbon::create(2014, 1, 1)->endOfDay();
$dt2 = $dt->copy()->startOfDay();
$littleHandRotations = $dt->diffFiltered(CarbonInterval::minute(), function(Carbon $date) {
return $date->minute === 0;
}, $dt2, true); // true as last parameter returns absolute value
echo $littleHandRotations; // 24
$date = Carbon::now()->addSeconds(3666);
echo $date->diffInSeconds(); // -3665.999827
echo $date->diffInMinutes(); // -61.099996683333
echo $date->diffInHours(); // -1.0183332733333
echo $date->diffInDays(); // -0.042430552881944
$date = Carbon::create(2016, 1, 5, 22, 40, 32);
echo $date->secondsSinceMidnight(); // 81632
echo $date->secondsUntilEndOfDay(); // 4767.999999
$date1 = Carbon::createMidnightDate(2016, 1, 5);
$date2 = Carbon::createMidnightDate(2017, 3, 15);
echo $date1->diffInDays($date2); // 435
echo $date1->diffInWeekdays($date2); // 311
echo $date1->diffInWeekendDays($date2); // 124
echo $date1->diffInWeeks($date2); // 62.142857142857
echo $date1->diffInMonths($date2); // 14.322580645161
echo $date1->diffInQuarters($date2); // 4.7741935483871
echo $date1->diffInYears($date2); // 1.1890410958904All diffIn*Filtered method take 1 callable filter as required parameter and a date object as optional second parameter, if missing, now is used. You may also pass true as third parameter to get absolute values.
For advanced handle of the week/weekend days, use the following tools:
echo implode(', ', Carbon::getDays()); // Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday
$saturday = new Carbon('first saturday of 2019');
$sunday = new Carbon('first sunday of 2019');
$monday = new Carbon('first monday of 2019');
echo implode(', ', Carbon::getWeekendDays()); // 6, 0
var_dump($saturday->isWeekend()); // bool(true)
var_dump($sunday->isWeekend()); // bool(true)
var_dump($monday->isWeekend()); // bool(false)
Carbon::setWeekendDays([
Carbon::SUNDAY,
Carbon::MONDAY,
]);
echo implode(', ', Carbon::getWeekendDays()); // 0, 1
var_dump($saturday->isWeekend()); // bool(false)
var_dump($sunday->isWeekend()); // bool(true)
var_dump($monday->isWeekend()); // bool(true)
Carbon::setWeekendDays([
Carbon::SATURDAY,
Carbon::SUNDAY,
]);
// weekend days and start/end of week or not linked
// start/end of week are driven by the locale
var_dump(Carbon::getWeekStartsAt()); // int(1)
var_dump(Carbon::getWeekEndsAt()); // int(0)
var_dump(Carbon::getWeekStartsAt('ar_EG')); // int(6)
var_dump(Carbon::getWeekEndsAt('ar_EG')); // int(5)