Complete set of PHP Date classes extensions:
class | extends | comment |
---|---|---|
Carbon | DateTime | |
CarbonImmutable | DateTimeImmutable | new |
CarbonInterface | DateTimeInterface | new |
CarbonTimeZone | DateTimeZone | new |
CarbonInterval | DateInterval | Read-only days property |
CarbonPeriod | DatePeriod | Blocked until php/php-src#3121 get merged |
Setter methods of Carbon become cloners in CarbonImmutable:
$m = new Carbon;
$c1 = $m->setDay(1);
// $m->day === $c1->day as $c1 === $m
$i = new CarbonImmutable;
$c2 = $i->setDay(1);
// $m->day !== $c2->day as $c2 is a new object
$c1->day = 9; // $m->day === 9
$c2->day = 9; // error, immutable
To reduce code amount, we could rather have a magic __call
method parsing methods matching actionUnit
with action in a given list (isSame
, isCurrent
, add
, sub
, get
, set
, floor
, ceil
, round
, etc.) and unit as valid unit (second
, minute
, hour
, day
, etc.) to route to generic method (action) with a unit argument.
This will enforce some methods consistency (easy way to handle singular/plural, same arguments for a given action). And a easier way to add actions. This would encourage to drop boolean arguments (which give multiple responsability to a single method) in favor of adding methods.
A automated script could update the PHPDoc comment to add @method
annotations so even if the methods does not really exist, IDE autocompletion will propose magic methods and we would not have to add them all manually.
Having a methods set compatible with https://momentjs.com could help to create a full-stack standard.
Critical methods should be final (macro methods, magic methods) so it would help us to prevent breaking changes in sub-classes.
Methods should be grouped in traits and each trait should remain stand-alone (could be taken alone).
Instead of extends the Carbon classes, users would be able to compose their own date classes picking traits.
Documentation could be interactive (see https://pug-demo.herokuapp.com and https://phug-lang.com/, it provides code examples the user can edit in live to see the PHP result).
Carbon become big, the single-page and one-level links menu will become a bit too limited, some search/expand/collapse tools would help to browse it.
Each method must be documented with minimal informations:
- history, example: added in 2.1.0, argument $foo added in 2.2.0, $foo can be an array since 2.2.1
- trait, example: set() belongs to Setter trait
- arguments, return and exceptions thrown
- code examples
To provide reliable solid library, Carbon should rely on a full microseconds support, that means at least PHP 7.1.8.
Carbon is widely used. We should not abandon v1 users.
- V1 documentation must remain available
- An issue templating and 1.x/2.x tagging will help to handle issues
- A migration guide could help user to upgrade
- Dropped methods could remain in the documentation (tagged as obsolete with some gray-styling and collapsed description)
First of all, great writeup - thanks! Here are my thoughts on the points you brought up:
PHP class compatibility
Extending all of PHPs core methods seems like a solid move. It should make Carbon able to be used interchangeably and seamlessly. I just read through the documentation for the native methods - while i do think we can make some solid additions, i could not find something to persuade me to break compatibility. Unless someone can come up with a case where the PHP implementation just does not cut it, i would say we should go for it.
The naming for the DateTimeZone is subject to discussion:
For the other Classes, the naming is on point.
Generic methods
Good suggestion. For the roadmap, i would not focus on the implementation details that much though - who cares if it is using magic methods under the hood?
We should settle on a list of units to support. The basics are
year
,month
,day
,hour
,minute
,second
. What aboutquarter
,week
,microsecond
? Any others?There are some differences between what those methods need, this should be a list of methods that should work on any unit:
We should put a strong focus on making those methods work consistently across units and offer implementations for all the standard units in a first release for 2.x. If we manage to reduce the number of methods and shrink Carbon as a whole, that would be great.
Stricter Extends
If we declare something as
final
, we should make sure to offer a way of extending functionality, if so needed. For example, we could do something like the pattern of bootable traits that Laravel uses, see here http://www.archybold.com/blog/post/booting-eloquent-model-traitsTraits
I do like traits as a way of splitting code and grouping methods. On the other hand, given that the
Carbon
class is "pure" in a way, meaning that it does not have side effects or require adapters, integrations..., i do not see why you would need to replace parts of it or mix and match different traits.Do you have a use case for that? From my perspective, the ~4500 lines of Carbon are a bit much but not to the point where it is becoming an issue.
Documentation
One of the key points of great documentation for me is seeing code + explanation and in the case of carbon, a result of that code.
The docs for react-router are a great example of having those side-by-side.
For the experimental bit - sure, a playground of some sort would be a nice touch.
Requirements
Fully agree on the microseconds support. Having PHP 7.1 as a minimum requirement enables as to use strict types as well so i am all for that.
About version 1.x
We could put the docs for 1.x and 2.x on the same page, preferrably in a similar format and have a dropdown selector for which version to use.