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

Change the signatures to use \DateTimeInterface instead \DateTime #84

Closed
burzum opened this issue Feb 28, 2016 · 23 comments
Closed

Change the signatures to use \DateTimeInterface instead \DateTime #84

burzum opened this issue Feb 28, 2016 · 23 comments

Comments

@burzum
Copy link

burzum commented Feb 28, 2016

The current implementation makes it impossible to use any custom implementation of a date time object.

Also it would be good to be able to tell the lib which object it should construct.

$dtTmp = new \DateTime('now', $timezone);

There are a few places where this is hard coded. I've seen the DateTime object is used a lot in at least three classes. So changing this is pretty difficult without overloading lots of methods.

A possible solution to the second problem could be a trait:

namespace Recurr;

trait DateConstructorTrait {

    protected $dateTimeClass = '\DateTime';

    public function setDateTimeClass($class)
    {
        $this->classChecker($class);
        $this->dateTimeClass = $class;
    }

    public function getDateTime($time = 'now', \DateTimeZone $timezone = NULL)
    {
        $class = $this->dateTimeClass;
        return new $class($time, $timezone);
    }

    protected function classChecker($class)
    {
        if (!class_exists($class)) {
            throw new \RuntimeException(sprintf('Class %s does not exist!', $class));
        }
    }
}

And replace the new \DateTime() calls with $this->getDateTime().

@cmfcmf
Copy link

cmfcmf commented Feb 29, 2016

The current implementation makes it impossible to use any custom implementation of a date time object.

Well, changing to \DateTimeInterface doesn't make it much better, because according to http://php.net/manual/de/class.datetimeinterface.php, userland classes cannot implement the interface themselves.

@cmfcmf
Copy link

cmfcmf commented Feb 29, 2016

Also, this makes the library incompatible with PHP < 5.5.0.

@burzum
Copy link
Author

burzum commented Mar 1, 2016

OK, I agree, I haven't seen this when I looked at the docs for the interface.

What about the date constructor trait? This would allow me to use it with Chronos.

@simshaun
Copy link
Owner

simshaun commented Mar 2, 2016

Implementing DateTimeInterface would be the proper solution here. I'm a little hesitant to increase the PHP version requirement to 5.5 for what I consider to be a minor improvement. I'll think about it.

@burzum
Copy link
Author

burzum commented Mar 2, 2016

@simshaun you can't implement DatetimeInterface.

Trying to implement DateTimeInterface raises a fatal error now. Formerly implementing the interface didn't raise an error, but the behavior was erroneous.

But about the php version, check http://php.net/eol.php, 5.4 reached it's end of life 5 month ago.

@simshaun
Copy link
Owner

simshaun commented Mar 2, 2016

I should have worded that differently. I meant "integrate by type hinting". While userland classes can't implement the interface, it would still allow libraries that extend \DateTime or \DateTimeImmutable to be passed in to Recurr.

Also, I know 5.4 is end-of-life, but a large number of people are still

@simshaun simshaun closed this as completed Mar 2, 2016
@simshaun simshaun reopened this Mar 2, 2016
@simshaun
Copy link
Owner

simshaun commented Mar 2, 2016

Accidentally hit close button on phone...

Anyway, a large number of people are still on 5.4. I still don't think this an important enough feature to warrant raising the requirement.

@brianmuse
Copy link

brianmuse commented Jun 20, 2016

This makes it pretty difficult to use this library with DateTimeImmutable, which is definitely preferred to the mutable DateTime. Perhaps you could merge the change but tag a major version bump so that those on 5.4 or earlier can still lock into their current version of this library?

You can see from the below link that the vast majority of projects are now 5.5 or greater, and official support for php 5.4 ended about a year ago (http://php.net/supported-versions.php). Even 5.5 is near EOL.

https://seld.be/notes/php-versions-stats-2016-1-edition

Also, I'm not sure using a trait is such a great idea. I think that #85 is a good path, but it may be even better to just switch over to DateTimeImmutable entirely instead of the interface.

@simshaun simshaun added this to the 2.0 milestone Aug 11, 2016
@simshaun
Copy link
Owner

Version requirement will be raised and this will be implemented for 2.0.

@foaly-nr1
Copy link
Contributor

Didn't make it into 2.0, did it? Would a PR be helpful at all?

@simshaun
Copy link
Owner

A PR would be welcome, thanks.

foaly-nr1 pushed a commit to foaly-nr1/recurr that referenced this issue Jul 11, 2017
simshaun pushed a commit that referenced this issue Jul 14, 2017
* Typehint \DateTimeInterface instead of \DateTime. Resolves #84

* Bump required minimum PHP version to 5.5
@simshaun simshaun removed this from the Major Rewrite milestone Jul 14, 2017
@simshaun
Copy link
Owner

Thanks to @foaly-nr1, this has been done. Due to the method signature changes, I've released this in v3.0.

https://github.com/simshaun/recurr/releases/tag/v3.0

@afoeder
Copy link

afoeder commented Sep 14, 2017

I'd like again to throw in that DateTimeImmutable thing because at the moment the annotations are to return DateTimeInterface which is unfortunately not very helpful, I'd say it "improved to the worse": now you don't know what exactly to expect.
I work with DateTimeImmutable all across my code and I can't event just DateTimeImmutable::createFromMutable() because I first have to check if the DateTimeInterface is actually a DateTime.
So, I would vote to replace everything with DateTimeImmutable, change the signature to DateTimeImmutable. This would also be b/c compatible because when adapting people expect DateTimeInterface, they would be satisfied with DateTimeImmutable.

@foaly-nr1
Copy link
Contributor

@afoeder whenever you use interfaces you won't know what implementation to expect but there is rarely a need to know. The use of interfaces for type hints has widely been accepted as best practice.

@afoeder
Copy link

afoeder commented Sep 14, 2017

@foaly-nr1 still not sure whether I agree on return types being interfaces in concrete classes. In a concrete class one should know better what to return than an interface.
That way the only sane way to go for me is to

// $recurrence being \Recurr\Recurrence
new \DateTimeImmutable($recurrence->getStart()->format(\DateTime::ATOM));

@foaly-nr1
Copy link
Contributor

@afoeder a good part of this library returns whatever concrete class you pass into it. So we'd end up with some return types being concrete and some being interfaces. That seems worse to me.

@afoeder
Copy link

afoeder commented Sep 14, 2017

that's kind of exactly why I think annotating interfaces is/was made too easy. There are mixed return types and annotating interfaces is just "slightly" better.
For the given case passing in DateTimeImmutable did nonetheless result in a DateTime; just look out for $dtTmp in \Recurr\Transformer\ArrayTransformer

And "some being concrete and some being interfaces" would still be better than all being interfaces, at least adopters know what to trust.

@foaly-nr1
Copy link
Contributor

You can still use a DateTime exactly like you'd use a DateTimeImmutable can't you?

@afoeder
Copy link

afoeder commented Sep 14, 2017

not when my further code relies on (whatever DateTime or DateTimeImmutable)

@foaly-nr1
Copy link
Contributor

I can't think of an example where your code relies on the concrete class apart from type hints. Can you give me an example?

@afoeder
Copy link

afoeder commented Sep 14, 2017

hmm I think I didn't get you… I meant "…when my further code relies on concrete DateTime or DateTimeImmutable"; doesn't matter which one, just: when my code does not rely on the interface type hint but the concrete type hint.

@foaly-nr1
Copy link
Contributor

How can code rely on DateTimeImmutable and not work when it gets a DateTime? I think it'll always work with both, won't it?

@afoeder
Copy link

afoeder commented Sep 19, 2017

[sorry, forgot to reply]:

type hints: i.e. when prescribing DateTimeImmutable via type hints; that's what I mean: all my code expects DateTimeImmutable except when otherwise required; I don't have such a case though and I honestly also can't think of one.

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

No branches or pull requests

6 participants