Set day with no overflow (with PHP Carbon)
Asked Answered
C

4

8

I use Carbon (PHP library) to set day to a date. But I want it not going to the next month, but rather stop and the end of month. Example:

Carbon::create(2018, 2, 27, 0, 0, 0)->day(31);

I'm getting

2018-03-03 00:00:00

But I need

2018-02-28 00:00:00

When you operate months Carbon gives you ->subMonthsNoOverflow() and ->addMonthsNoOverflow() which is really helpful but there is nothing like this for setting a day.

Cosby answered 12/7, 2018 at 0:35 Comment(0)
C
3

The answer is

$day = 31;
$date = Carbon::create(2018, 2, 27, 0, 0, 0);
$date->day(min($day, $date->daysInMonth));
Cosby answered 5/5, 2021 at 3:27 Comment(1)
stable solution.Workaday
F
8

Since Carbon 2.0 they have added a method setUnitNoOverflow($unit, $value, $overflowUnit) but it's still undocumented.

I managed to get 2019-02-28 by doing it like this

Carbon::parse('2019-02-01')->setUnitNoOverflow('day', 31, 'month')->format('Y-m-d')
 Carbon\Carbon @1551398399 {#3013
     date: 2019-02-28 23:59:59.999999 UTC (+00:00),
   }

Alternatively you can use addUnitNoOverflow and subUnitNoOverflow

Issue github - Source

Final answered 20/11, 2019 at 19:26 Comment(2)
Don't know if it was previously undocumented, but the documentation has since been properly documented. Carbon docs link It's among the add and subtract date with an example for setting hour units without overflowing the day. Asume it won't overflow the month either, since month isn't overflowing.Voluntarism
Thanks for the link. I could have missed that in the doc as well.Deliberate
C
3

The answer is

$day = 31;
$date = Carbon::create(2018, 2, 27, 0, 0, 0);
$date->day(min($day, $date->daysInMonth));
Cosby answered 5/5, 2021 at 3:27 Comment(1)
stable solution.Workaday
P
2

Can you use endOfMonth() instead?

Carbon::create(2018, 2, 27, 0, 0, 0)->endOfMonth();

There's a full list of modifiers in the Carbon documentation.

Pasadis answered 12/7, 2018 at 0:42 Comment(7)
NO, what If I need it on 30-th? I need it on a day, not on an end of month.Cosby
February 30th does not exist, so endOfMonth() will give you Feb 28th (or 29th on a leap year). On other months that do contain 30 or 31 days, it will return that date, i.e., March 31st.Pasadis
And on January I'll get 31-st instead of 30-th.Cosby
Yes, Carbon::create(2018, 1, 27, 0, 0, 0)->endOfMonth(); would give you January 31st.Pasadis
I need to set day to a date. Say I need 30-th. For januarry It will be '->day(30);' but for februarry it will fail.Cosby
@YevgeniyAfanasyev So you'd like to be able to set the 30th of every month, except February, which would be 28th (or 29th on leap years). Is that correct?Pasadis
No, I want to set a day to a carbon instance. same way that carbon function ->day($d) works, but if the month does not have this day this function gives me another month, I don't want that, I want a last day of the month instead.Cosby
P
-2

Is very simple:

$date = Carbon\Carbon::now();
$date->day = 10;
$date->month = 1;
$date->year = 2021;

Or

Carbon\Carbon::parse("2021-10-01")

Docs: https://carbon.nesbot.com/docs/#api-setters

Pectoral answered 4/5, 2021 at 13:31 Comment(1)
If you apply your solution to the given exemple in February, you will end up with the same overflow issue. This does not work any better.Cockhorse

© 2022 - 2024 — McMap. All rights reserved.