Skip to content

Added missing obj methods to DateTimeInterface #13491

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

Closed

Conversation

marc-mabe
Copy link
Contributor

DateTimeInterface can not be implemented by user land which limits the interface to DateTime and DateTimeImmutable
but it's missing a lot of object methods available in both DateTime and DateTimeImmutable.

This makes your static analyzers (IDE, PHPStan and friends, ...) know which methods to expect.

Question: The interface already has __wakeup(), __serialize(), __unserialize() but not __set_state() which I personally would not expect in an interface if there isb't a very good reason ...

  • Is there actually a very good reason?
  • Could these be removed without BC break? (again the interface isn't allowed for user land)
  • Should __set_state() be added as well?

NOTE: This somehow depends on #13486 or vise versa.

Copy link
Member

@kocsismate kocsismate left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There are vague plans to deprecate and remove DateTime, in which case the interface should be deprecated if we want to keep disallowing userland implementations, or otherwise I think the mutator methods could be added to the interface after the interface assumes/requires an immutable implementation.

@@ -316,12 +316,43 @@ interface DateTimeInterface
/** @tentative-return-type */
public function format(string $format): string;

/** @tentative-return-type */
public function modify(string $modifier): DateTimeInterface|false;
Copy link
Member

@kocsismate kocsismate Feb 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO adding any mutator methods to the interface is not applicable now, because the two implementations have different behavior regarding mutability. In practice, this means that users of the DateTimeInterface should deal with the possibility that the interface implementation is either mutable or immutable.

function setTime(DateTimeInterface $d) {
    $d1 = clone $d;                     // cloning is needed as a defensive measure
    $d1->modify("+1 days");

    return $d1;
}

Copy link
Contributor Author

@marc-mabe marc-mabe Mar 6, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, the behavior is different, but this kind of difference is not possible to be defined in method signatures.

Actually your example should be

function setTime(DateTimeInterface $d) {
    $new = clone $d;
    $new = $new->modify("+1 days");

    return $new;
}

Copy link

@ghost ghost Mar 8, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree mutator methods should not be added. When one works with an interface instance it's impossible to know whether it's a mutable or immutable instance. If PHPStan, IDE etc. need some more information then we can write stub files for them. I would leave it as is (hoping this interface will be removed together with mutable class).

/** @tentative-return-type */
public function getOffset(): int;

/** @tentative-return-type */
public function getMicroseconds(): int; // TODO: Rename https://github.com/php/php-src/pull/13486
Copy link
Member

@kocsismate kocsismate Feb 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one method is definitely missing from the interface right now, so maybe this one could be committed separately without any further discussion.

@marc-mabe
Copy link
Contributor Author

@kocsismate I totally agree, that the mutable DateTime should be deprecated but it's not the case yet and I haven't seen any RFC nor is it save it would pass. Anyway, I somehow completely missed the part that the interface does not contain mutators and it's even documented (the wording wasn't clear for me).

To go forward I would suggest the following ...

  1. I'll add getMicrosecond only to the interface in Singular DateTime::[get|set]Microsecond & no tentative return type #13486
  2. Remove __wakeup(), __serialize(), __unserialize() from interface in this PR
  3. update documentation to
    a. make it more clear that the interface doesn't contain mutator methods - and why
    b. add example explicitly allowing both and correctly handle both behaviors
function nextDay(DateTime|DateTimeImmutable $d) {
    $new = clone $d;
    $new = $new->modify("+1 days");

    return $new;
}

What do you think ?

@ghost
Copy link

ghost commented Mar 8, 2024

There are vague plans to deprecate and remove DateTime

@kocsismate can you elaborate? Are there any plans more recent than Derick's tweet from 1.5 year ago https://twitter.com/derickr/status/1551611856007069696?lang=en?

@kocsismate
Copy link
Member

@javaDeveloperKid No, I am not aware of any specifics.

@kocsismate
Copy link
Member

To go forward I would suggest the following ...

@marc-mabe Yes, I agree with the plan, thank you for the improvements! I guess the removal of the magic methods from the interface would only affect people who call these methods directly for some weird reason (maybe some static analyisis issues could pop up) ^^ So I think the change is fine. But let's wait for Derick's opinion, since he was the one who added them to the interface.

@derickr
Copy link
Member

derickr commented Mar 18, 2024

I think there is nothing to do here now? The getMicroseconds was added I believe. And I don't think adding the mutator methods is a good idea, as they don't have the same behaviour (new object vs internally modified one).

@marc-mabe
Copy link
Contributor Author

I think there is nothing to do here now? The getMicroseconds was added I believe. And I don't think adding the mutator methods is a good idea, as they don't have the same behaviour (new object vs internally modified one).

Hi @derickr ,
Yes, but the open question is if we want to remove __wakeup(), __serialize(), __unserialize() from DateTimeInterface?

@derickr
Copy link
Member

derickr commented May 22, 2024

I am going to close this, until we have a new full thought-through API.

@derickr derickr closed this May 22, 2024
@marc-mabe marc-mabe deleted the DateTimeInterface-missing-methods branch May 22, 2024 08:58
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants