Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Carbon - why addMonths() change the day of month?

Here's the simple example (today is 2016-08-29):

var_dump(Carbon::now());
var_dump(Carbon::now()->addMonths(6));

Output:

object(Carbon\Carbon)#303 (3) {
  ["date"] => string(26) "2016-08-29 15:37:11.000000"
}
object(Carbon\Carbon)#303 (3) {
  ["date"] => string(26) "2017-03-01 15:37:11.000000"
}

For Carbon::now()->addMonths(6) I'm expecting 2017-02-29, not 2017-03-01.

Am I missing something about date modifications?

like image 516
Limon Monte Avatar asked Aug 29 '16 13:08

Limon Monte


People also ask

How does carbon get day name from date?

Get Day From Date In Laravel Carbon provides the format() method which is used to format the date as we want. We can also get the day name from the date. Also, this function is useful to change any kind of date format like we are doing in PHP's date() function. Let's see simple examples.

How do you set the date on carbon?

Carbon also allows us to generate dates and times based on a set of parameters. For example, to create a new Carbon instance for a specific date use the Carbon::createFromDate() method, passing in the year, month, day, and timezone, as in the following example.

How do you find the date on a carbon object?

You can use array_map to produce this kind of result: $dates_formatted = array_map(function($entry) { // transform the Carbon object to something like 'Dec 25, 1975' return $entry['date']->toFormattedDateString(); }, $dates);


2 Answers

It's even more crippled than that - subtraction has same issues. There are special methods to avoid overflows, though:

function original(){ 
    return new Carbon('2016-08-31'); 
};
function print_dt($name, $date){ 
    echo $name . $date->toAtomString() . PHP_EOL; 
};

print_dt('original:            ', original());
echo '-----' . PHP_EOL;
print_dt('addMonths:           ', original()->addMonths(6));
print_dt('addMonthsNoOverflow: ', original()->addMonthsNoOverflow(6));
echo '-----' . PHP_EOL;
print_dt('subMonths:           ', original()->subMonths(2));
print_dt('subMonthsNoOverflow: ', original()->subMonthsNoOverflow(2));

output:

original:            2016-08-31T00:00:00+00:00
----- 
addMonths:           2017-03-03T00:00:00+00:00
addMonthsNoOverflow: 2017-02-28T00:00:00+00:00
----- 
subMonths:           2016-07-01T00:00:00+00:00
subMonthsNoOverflow: 2016-06-30T00:00:00+00:00
like image 121
Alexander Malakhov Avatar answered Oct 06 '22 20:10

Alexander Malakhov


There is no 2/29/2017. Leap-year happened in 2016.

The following link:

http://carbon.nesbot.com/docs/#api-addsub

provides an example of adding 1 month to 1/31/2012 and arriving on 3/3/2012. Which is intended, though seems confusing to me.


As a counter-example exhibiting different behavior, in SQL:

SELECT dateadd(m,1,'2012-01-31') 

results in 2/29/2012, so it would be a good idea to check the specifications of whatever addmonth() function you plan on using.

like image 41
RIanGillis Avatar answered Oct 06 '22 19:10

RIanGillis