问题
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