Addition and Subtraction
The default DateTime provides a couple of different methods for easily adding and subtracting time. There is modify(), add() and sub(). change() is an enhanced version of modify() that can take magical date/time format string, 'last day of next month', that it parses and applies the modification while add() and sub() can take the same the same kind of string, intervals (DateInterval or CarbonInterval) or count+unit parameters. But you can still access the native methods of DateTime class using rawAdd() and rawSub().
$dt = CarbonImmutable::create(2012, 1, 15, 0);
echo $dt->toDateTimeString(); // 2012-01-15 00:00:00
echo $dt->addCenturies(5); // 2512-01-15 00:00:00
echo $dt->addCentury(); // 2112-01-15 00:00:00
echo $dt->subCentury(); // 1912-01-15 00:00:00
echo $dt->subCenturies(5); // 1512-01-15 00:00:00
echo $dt->addYears(5); // 2017-01-15 00:00:00
echo $dt->addYear(); // 2013-01-15 00:00:00
echo $dt->subYear(); // 2011-01-15 00:00:00
echo $dt->subYears(5); // 2007-01-15 00:00:00
echo $dt->addQuarters(2); // 2012-07-15 00:00:00
echo $dt->addQuarter(); // 2012-04-15 00:00:00
echo $dt->subQuarter(); // 2011-10-15 00:00:00
echo $dt->subQuarters(2); // 2011-07-15 00:00:00
echo $dt->addMonths(60); // 2017-01-15 00:00:00
echo $dt->addMonth(); // 2012-02-15 00:00:00 // equivalent of $dt->month($dt->month + 1); so it wraps
echo $dt->subMonth(); // 2011-12-15 00:00:00
echo $dt->subMonths(60); // 2007-01-15 00:00:00
echo $dt->addDays(29); // 2012-02-13 00:00:00
echo $dt->addDay(); // 2012-01-16 00:00:00
echo $dt->subDay(); // 2012-01-14 00:00:00
echo $dt->subDays(29); // 2011-12-17 00:00:00
echo $dt->addWeekdays(4); // 2012-01-19 00:00:00
echo $dt->addWeekday(); // 2012-01-16 00:00:00
echo $dt->subWeekday(); // 2012-01-13 00:00:00
echo $dt->subWeekdays(4); // 2012-01-10 00:00:00
echo $dt->addWeeks(3); // 2012-02-05 00:00:00
echo $dt->addWeek(); // 2012-01-22 00:00:00
echo $dt->subWeek(); // 2012-01-08 00:00:00
echo $dt->subWeeks(3); // 2011-12-25 00:00:00
echo $dt->addHours(24); // 2012-01-16 00:00:00
echo $dt->addHour(); // 2012-01-15 01:00:00
echo $dt->subHour(); // 2012-01-14 23:00:00
echo $dt->subHours(24); // 2012-01-14 00:00:00
echo $dt->addMinutes(61); // 2012-01-15 01:01:00
echo $dt->addMinute(); // 2012-01-15 00:01:00
echo $dt->subMinute(); // 2012-01-14 23:59:00
echo $dt->subMinutes(61); // 2012-01-14 22:59:00
echo $dt->addSeconds(61); // 2012-01-15 00:01:01
echo $dt->addSecond(); // 2012-01-15 00:00:01
echo $dt->subSecond(); // 2012-01-14 23:59:59
echo $dt->subSeconds(61); // 2012-01-14 23:58:59
echo $dt->addMilliseconds(61); // 2012-01-15 00:00:00
echo $dt->addMillisecond(); // 2012-01-15 00:00:00
echo $dt->subMillisecond(); // 2012-01-14 23:59:59
echo $dt->subMillisecond(61); // 2012-01-14 23:59:59
echo $dt->addMicroseconds(61); // 2012-01-15 00:00:00
echo $dt->addMicrosecond(); // 2012-01-15 00:00:00
echo $dt->subMicrosecond(); // 2012-01-14 23:59:59
echo $dt->subMicroseconds(61); // 2012-01-14 23:59:59
// and so on for any unit: millenium, century, decade, year, quarter, month, week, day, weekday,
// hour, minute, second, microsecond.
// Generic methods add/sub (or subtract alias) can take many different arguments:
echo $dt->add(61, 'seconds'); // 2012-01-15 00:01:01
echo $dt->sub('1 day'); // 2012-01-14 00:00:00
echo $dt->add(CarbonInterval::months(2)); // 2012-03-15 00:00:00
echo $dt->subtract(new \DateInterval('PT1H')); // 2012-01-14 23:00:00
// You can also add or subtract multiple units at once with:
echo $dt->plus(days: 2, hours: 12, minutes: 30); // 2012-01-17 12:30:00
echo $dt->minus(years: 1, seconds: 120); // 2011-01-14 23:58:00
// plus() and minus() can take float numbers for any unit except month and years:
echo $dt->plus(days: 0.5); // 2012-01-15 12:00:00You can also pass negative values to addXXX(), in fact that's how subXXX() is implemented.
P.S. Don't worry if you forget and use addDay(5) or subYear(3) (singular), I have your back 😉
By default, Carbon relies on the underlying parent class PHP DateTime behavior. As a result adding or subtracting months can overflow, example:
$dt = CarbonImmutable::create(2017, 1, 31, 0);
echo $dt->addMonth(); // 2017-03-03 00:00:00
echo "\n";
echo $dt->subMonths(2); // 2016-12-01 00:00:00Since Carbon 2, you can set a local overflow behavior for each instance:
$dt = CarbonImmutable::create(2017, 1, 31, 0);
$dt->settings([
'monthOverflow' => false,
]);
echo $dt->addMonth(); // 2017-02-28 00:00:00
echo "\n";
echo $dt->subMonths(2); // 2016-11-30 00:00:00This will apply for methods addMonth(s), subMonth(s), add($x, 'month'), sub($x, 'month') and equivalent quarter methods. But it won't apply for intervals objects or strings like add(CarbonInterval::month()) or add('1 month').
Note that CarbonInterval::monthNoOverflow() is available to produce an interval of 1 month that does not overflow. CarbonInterval::monthWithAnchorDay() is also available and allow you to specify an anchor day (after stepping to the next month it will try to go up to the given anchor day if available, else it will go to the last day of the month).
Because the same can also happen when adding/subtracting year(s) starting from a February 29th (leap year), then there also exist CarbonInterval::yearNoOverflow() and CarbonInterval::yearWithAnchorDay().
Same overflow mode are available with plus() and minus():
// It can take an overflow mode:
echo CarbonImmutable::create(2012, 1, 31)->plus(
months: 1,
overflow: OverflowMode::NoOverflow,
); // 2012-02-29 00:00:00
// (overflow: false is a shortcut for overflow: OverflowMode::NoOverflow)
// Or it can take an anchorDay:
echo CarbonImmutable::create(2012, 2, 28)
->plus(months: 1, anchorDay: 30); // 2012-03-30 00:00:00
// Meaning that after adding months/years, it will try to set current day to this number
// if it exists in the current month, else it will go to the last day of the monthIf overflow is set to OverflowMode::AnchorDay without specifying anchorDay it will use the day of the initial date.
You also can use ->addMonthsNoOverflow, ->subMonthsNoOverflow, ->addMonthsWithOverflow and ->subMonthsWithOverflow (or the singular methods with no s to "month") to explicitly add/sub months with or without overflow no matter the current mode and the same for any bigger unit (quarter, year, decade, century, millennium).
$dt = Carbon::createMidnightDate(2017, 1, 31)->settings([
'monthOverflow' => false,
]);
echo $dt->copy()->addMonthWithOverflow(); // 2017-03-03 00:00:00
// plural addMonthsWithOverflow() method is also available
echo $dt->copy()->subMonthsWithOverflow(2); // 2016-12-01 00:00:00
// singular subMonthWithOverflow() method is also available
echo $dt->copy()->addMonthNoOverflow(); // 2017-02-28 00:00:00
// plural addMonthsNoOverflow() method is also available
echo $dt->copy()->subMonthsNoOverflow(2); // 2016-11-30 00:00:00
// singular subMonthNoOverflow() method is also available
echo $dt->copy()->addMonth(); // 2017-02-28 00:00:00
echo $dt->copy()->subMonths(2); // 2016-11-30 00:00:00
$dt = Carbon::createMidnightDate(2017, 1, 31)->settings([
'monthOverflow' => true,
]);
echo $dt->copy()->addMonthWithOverflow(); // 2017-03-03 00:00:00
echo $dt->copy()->subMonthsWithOverflow(2); // 2016-12-01 00:00:00
echo $dt->copy()->addMonthNoOverflow(); // 2017-02-28 00:00:00
echo $dt->copy()->subMonthsNoOverflow(2); // 2016-11-30 00:00:00
echo $dt->copy()->addMonth(); // 2017-03-03 00:00:00
echo $dt->copy()->subMonths(2); // 2016-12-01 00:00:00The same is available for years.
You also can control overflow for any unit when working with unknown inputs:
$dt = CarbonImmutable::create(2018, 8, 30, 12, 00, 00);
// Add hours without overflowing day
echo $dt->addUnitNoOverflow('hour', 7, 'day'); // 2018-08-30 19:00:00
echo "\n";
echo $dt->addUnitNoOverflow('hour', 14, 'day'); // 2018-08-30 23:59:59
echo "\n";
echo $dt->addUnitNoOverflow('hour', 48, 'day'); // 2018-08-30 23:59:59
echo "\n-------\n"; // -------
// Substract hours without overflowing day
echo $dt->subUnitNoOverflow('hour', 7, 'day'); // 2018-08-30 05:00:00
echo "\n";
echo $dt->subUnitNoOverflow('hour', 14, 'day'); // 2018-08-30 00:00:00
echo "\n";
echo $dt->subUnitNoOverflow('hour', 48, 'day'); // 2018-08-30 00:00:00
echo "\n-------\n"; // -------
// Set hours without overflowing day
echo $dt->setUnitNoOverflow('hour', -7, 'day'); // 2018-08-30 00:00:00
echo "\n";
echo $dt->setUnitNoOverflow('hour', 14, 'day'); // 2018-08-30 14:00:00
echo "\n";
echo $dt->setUnitNoOverflow('hour', 25, 'day'); // 2018-08-30 23:59:59
echo "\n-------\n"; // -------
// Adding hours without overflowing month
echo $dt->addUnitNoOverflow('hour', 7, 'month'); // 2018-08-30 19:00:00
echo "\n";
echo $dt->addUnitNoOverflow('hour', 14, 'month'); // 2018-08-31 02:00:00
echo "\n";
echo $dt->addUnitNoOverflow('hour', 48, 'month'); // 2018-08-31 23:59:59
echo "\n-------\n"; // -------
// An anchor day can be passed so try to go up to
// this day if it exists in the current month
echo $dt->addUnitNoOverflow(Unit::Month, 2, Unit::Year, 31); // 2018-10-31 12:00:00
echo "\n";
echo $dt->subUnitNoOverflow(Unit::Month, 2, Unit::Year, 31); // 2018-06-30 12:00:00
echo "\n";
echo $dt->setUnitNoOverflow(Unit::Month, 9, Unit::Year, 31); // 2018-09-30 12:00:00Any modifiable unit can be passed as argument of those methods:
$units = [];
foreach (['millennium', 'century', 'decade', 'year', 'quarter', 'month', 'week', 'weekday', 'day', 'hour', 'minute', 'second', 'millisecond', 'microsecond'] as $unit) {
$units[$unit] = Carbon::isModifiableUnit($unit);
}
echo json_encode($units, JSON_PRETTY_PRINT);
/*
{
"millennium": true,
"century": true,
"decade": true,
"year": true,
"quarter": true,
"month": true,
"week": true,
"weekday": true,
"day": true,
"hour": true,
"minute": true,
"second": true,
"millisecond": true,
"microsecond": true
}
*/Static helpers exist but are deprecated. If you're sure to need to apply global setting or work with version 1 of Carbon, check the section below:
Overflow static helpers
You can prevent the overflow with Carbon::useMonthsOverflow(false)
Carbon::useMonthsOverflow(false);
$dt = Carbon::createMidnightDate(2017, 1, 31);
echo $dt->copy()->addMonth(); // 2017-02-28 00:00:00
echo "\n";
echo $dt->copy()->subMonths(2); // 2016-11-30 00:00:00
// Call the method with true to allow overflow again
Carbon::resetMonthsOverflow(); // same as Carbon::useMonthsOverflow(true);The method Carbon::shouldOverflowMonths() allows you to know if the overflow is currently enabled.
Carbon::useMonthsOverflow(false);
$dt = Carbon::createMidnightDate(2017, 1, 31);
echo $dt->copy()->addMonthWithOverflow(); // 2017-03-03 00:00:00
// plural addMonthsWithOverflow() method is also available
echo $dt->copy()->subMonthsWithOverflow(2); // 2016-12-01 00:00:00
// singular subMonthWithOverflow() method is also available
echo $dt->copy()->addMonthNoOverflow(); // 2017-02-28 00:00:00
// plural addMonthsNoOverflow() method is also available
echo $dt->copy()->subMonthsNoOverflow(2); // 2016-11-30 00:00:00
// singular subMonthNoOverflow() method is also available
echo $dt->copy()->addMonth(); // 2017-02-28 00:00:00
echo $dt->copy()->subMonths(2); // 2016-11-30 00:00:00
Carbon::useMonthsOverflow(true);
$dt = Carbon::createMidnightDate(2017, 1, 31);
echo $dt->copy()->addMonthWithOverflow(); // 2017-03-03 00:00:00
echo $dt->copy()->subMonthsWithOverflow(2); // 2016-12-01 00:00:00
echo $dt->copy()->addMonthNoOverflow(); // 2017-02-28 00:00:00
echo $dt->copy()->subMonthsNoOverflow(2); // 2016-11-30 00:00:00
echo $dt->copy()->addMonth(); // 2017-03-03 00:00:00
echo $dt->copy()->subMonths(2); // 2016-12-01 00:00:00
Carbon::resetMonthsOverflow();From version 1.23.0, overflow control is also available on years:
Carbon::useYearsOverflow(false);
$dt = Carbon::createMidnightDate(2020, 2, 29);
var_dump(Carbon::shouldOverflowYears()); // bool(false)
echo $dt->copy()->addYearWithOverflow(); // 2021-03-01 00:00:00
// plural addYearsWithOverflow() method is also available
echo $dt->copy()->subYearsWithOverflow(2); // 2018-03-01 00:00:00
// singular subYearWithOverflow() method is also available
echo $dt->copy()->addYearNoOverflow(); // 2021-02-28 00:00:00
// plural addYearsNoOverflow() method is also available
echo $dt->copy()->subYearsNoOverflow(2); // 2018-02-28 00:00:00
// singular subYearNoOverflow() method is also available
echo $dt->copy()->addYear(); // 2021-02-28 00:00:00
echo $dt->copy()->subYears(2); // 2018-02-28 00:00:00
Carbon::useYearsOverflow(true);
$dt = Carbon::createMidnightDate(2020, 2, 29);
var_dump(Carbon::shouldOverflowYears()); // bool(true)
echo $dt->copy()->addYearWithOverflow(); // 2021-03-01 00:00:00
echo $dt->copy()->subYearsWithOverflow(2); // 2018-03-01 00:00:00
echo $dt->copy()->addYearNoOverflow(); // 2021-02-28 00:00:00
echo $dt->copy()->subYearsNoOverflow(2); // 2018-02-28 00:00:00
echo $dt->copy()->addYear(); // 2021-03-01 00:00:00
echo $dt->copy()->subYears(2); // 2018-03-01 00:00:00
Carbon::resetYearsOverflow();