Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CarbonInterval's days property return false #3018

Open
daniser opened this issue May 8, 2024 · 7 comments
Open

CarbonInterval's days property return false #3018

daniser opened this issue May 8, 2024 · 7 comments

Comments

@daniser
Copy link

daniser commented May 8, 2024

Hello,

I encountered an issue with the following code:

echo (new \DateTime('2024-05-08'))->diff(new \DateTime('2024-05-11'))->days;

3

echo (new \Carbon\Carbon('2024-05-08'))->diff(new \Carbon\Carbon('2024-05-11'))->days;

false

Carbon version: 3.3.1

PHP version: 8.3.4

I expected to get:

3

But I actually get:

false

Thanks!

@fxbt
Copy link

fxbt commented May 8, 2024

Before the 3.0, the Carbon::diff method simply returned a \DateInterval but now there is an intermediate CarbonInterval object that is created with an interval_spec string.

As stated in the DateInterval phpdoc

If the DateInterval object was created by DateTimeImmutable::diff() or DateTime::diff(), then this is the total number of full days between the start and end dates. Otherwise, days will be false.

It's a problem for the days property, it's never set and unfortunately it can't be set manually. I tried a lot of things but I don't think there is an easy solution to handle this directly in the vendor

@daniser You can replace all the Carbon::diff in your code with the Carbon::diffAsDateInterval method to keep the same behaviour, or you can use the Carbon::diffInDays method but you'll get a float so don't forget to cast it if you need an integer

@kylekatarnls
Copy link
Collaborator

You can also use ->format('%a') instead of ->days it's got overridden recently to behave the same way it would with a diff DateInterval

@mtx-z
Copy link

mtx-z commented Dec 11, 2024

This breaks compatibility with the package simshaun/recurr.

If we set a \Recurr\Rule dateTime property to a Carbon instance (ex $rule->setStartDate($carbonInstance)), it can fail when the package calls ->days on a ->diff() result, as the resulting interval will be a CarbonInterval (class file) instance instead of a DateInterval (class) one.
In this case, ->days returns null.

You should use ->toDateTime() on your Carbon instance before passing it to a Recurr method.

Example usage in Recurr package here.

@nickdnk
Copy link

nickdnk commented Jan 1, 2025

This doesn't just affect days. diff basically just doesn't work at all as advertised in phpdocs/autocomplete. It's very counterintuitive and error-prone and if it cannot be fixed I would suggest you simply get rid of diff.

Note that in the example below, the hours property has the description "Total hours of the current interval".

$now = Carbon::now();

$newDate = Carbon::now()
    ->subDays(4);

$d1 = $now->diff($newDate)->hours;
$d2 = $now->diffInHours($newDate);

echo 'diff: ' . $d1 . PHP_EOL;
echo 'diffInHours: ' . $d2 . PHP_EOL;

/**
 * Output:
 * diff: 23 // not even remotely correct
 * diffInHours: -95.999999995278 // correct
 */

Edit: I see totalHours does work, but that leaves me with the question: What is hours supposed to do then? Does it return the remainder of hours after days, or something, i.e. 3 days and 23 hours? It's a little confusing. But in that case it should still be negative.

Edit 2: Okay, it's the current hour, as in, the 23 hours at which I ran the command (which I did not notice because I am not in UTC). But in that case, I think the description of the diff interval needs some work, because it seems to indicate the number of hours difference, not the hour-on-the-clock after you add/sub the difference.

@kylekatarnls
Copy link
Collaborator

Hello,

it's the current hour, as in, the 23 hours at which I ran the command (which I did not notice because I am not in UTC)

No, 23 is the hours component of the diff in 3 days, 23 hours as you guessed, it's not negative because the whole interval is.

This is unrelated to this issue and this behavior directly comes from PHP itself from DateTime::diff. This is also the reason why we won't "get rid of diff", first because Carbon extends DateTime, so the method will always be there and ->hours would have the same value anyway if we remove the method override.

I suggest you var_dump($now->diff($newDate)) this way you will better understand what are the values for all the interval components.

the hours property has the description "Total hours of the current interval".

Indeed, this is wrong, we should fix this.

@nickdnk
Copy link

nickdnk commented Jan 2, 2025

Hello,

it's the current hour, as in, the 23 hours at which I ran the command (which I did not notice because I am not in UTC)

No, 23 is the hours component of the diff in 3 days, 23 hours as you guessed, it's not negative because the whole interval is.

What I meant was that this ended up at 23 because I ran the ::now() function at that hour and just subtracted 4 days.

the hours property has the description "Total hours of the current interval".

Indeed, this is wrong, we should fix this.

Cool, because this was the whole reason I made these wrong assumptions in the first place.

@kylekatarnls
Copy link
Collaborator

Documentation will be fixed via #3130

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants