Carbon get month by number returns march for number 2

…衆ロ難τιáo~ 提交于 2019-12-25 02:16:46

问题


Has anyone ever had this bug before, or know a way to fix it?

I want to get a list of all months in the current year (start date and end date) in an array, so i'm doing like this (open to suggestions for cleaner easier ways)

//Create a months array
$months = [];
//Get start and end of all months
for($i = 1; $i <= 12; $i++){
   $array = [];
   $array['start'] = Carbon::create()->month($i)->startOfMonth()->format('d/m/y');
   $array['end'] = Carbon::create()->month($i)->endOfMonth()->format('d/m/y');
   array_push($months, $array);
}

Which produces this result

As you can see, its looped and retrieved the months, but notice that it skips February completely and adds March twice.

If I manually run and return this code

return Carbon::create()->month(2)->startOfMonth()->format('d/m/y');

It returns 01/03/2018.

Why does carbon print out March for month 2? Has anyone ever had this issue before or know of a way to fix it?


回答1:


Carbon::create()->month(2) will first create today's date, and then set the month to 2, but keep the other values. Because today's date is the 29th of August, the date ends up referring to the 29th of February, which (this year at least) doesn't exist. PHP rolls these "fake" dates over into the next month, so February 29th becomes March 1st.

If you explicitly set the day of the month first, this should work as expected:

Carbon::create()->day(1)->month($i);

(Also, if you'd tried this yesterday it would have worked fine, and you might never have noticed the bug. If you tried it tomorrow, you would have ended up with March 2nd and probably noticed it a lot faster. Dates are great fun.)




回答2:


Pure PHP is enough for this:

$datePeriod = new \DatePeriod(
    new \DateTimeImmutable(date('01-01-Y')),
    new \DateInterval('P1M'),
    new \DateTimeImmutable(date('31-12-Y'))
);

$dates = [];
foreach ($datePeriod as $date) {
     $dates[] = [
         'start' => $date->modify('first day of this month')->format('d/m/y'),
         'end' => $date->modify('last day of this month')->format('d/m/y'),
     ];   
}



回答3:


It's 0 based by the looks. so month(0) would be January, 1 = February, etc. Change your loop to

for($i = 0; $i < 12; $i++){
   $array = [];
   $array['start'] = Carbon::create()->month($i)->startOfMonth()->format('d/m/y');
   $array['end'] = Carbon::create()->month($i)->endOfMonth()->format('d/m/y');
   array_push($months, $array);
}



回答4:


Figured this out whilst commenting on a suggested answer.

Its because todays date is 29th August 2018, and there are not 29 days in February.

Basically Carbon is creating an instance from todays date with Carbon::create() but then when using ->month(2) will try to get the 29th Feb and error. It needs to work from the first of the month so change it to

 Carbon::create()->startOfMonth()->month($i)->startOfMonth()->format('d/m/y');

So it references from the 1st of the month and it will work as expected.



来源:https://stackoverflow.com/questions/52072758/carbon-get-month-by-number-returns-march-for-number-2

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!