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)
Translator seems always simple at first sight, sounds like just a big mapping. But check the size of https://github.com/symfony/translation, it's not filled with air, it's really how tricky is the translation rules. Just have a look at pluralization rules to start: https://github.com/symfony/translation/blob/master/PluralizationRules.php
Nearly all the languages are already configured and ready to translate, ready to be customized by end-users and already documented. And Symfony is very well maintained so if a language is missing (it happened only once until now) they are very reactive, last time, they merged in less than 24 hours: symfony/symfony#27286
The symfony/translation dependency also means consistency between the app and Carbon for each one using Symfony/Laravel.
I prefer to focus on date features and rely on a dedicated package for translation.
About mutable/immutable, there are common ways.
modify()
exists on both for example but returns new object with Immutable. So we can create common interfaces likeModifyable
and trait with common methods usingmodify()
no matter it's mutable or not, then on unit tests, we can have a standard way to check it: