innmind / time-continuum
Library to manipulate time
Requires
- php: ~8.2
- innmind/immutable: ~4.0|~5.0
- psr/log: ~3.0
Requires (Dev)
- innmind/black-box: ~5.0
- innmind/coding-standard: ^2.0.1
- phpunit/phpunit: ~10.2
- vimeo/psalm: ~5.13
Suggests
- innmind/black-box: For property based testing
Provides
Conflicts
- innmind/black-box: <5.0|~6.0
README
This library allows you to handle time down to the millisecond. The point was to also be explicit for every component of dates, this is why every php magic strings have been converted into objects.
It also provides interfaces so you can make mocks for your unit tests, of course it's only helpful if you use an implementation of Clock
in your code instead of directly instanciating dates.
All objects are immutable.
Installation
composer install innmind/time-continuum
Usage
use Innmind\TimeContinuum\{ Earth\Clock, PointInTime, }; use Innmind\Immutable\Maybe; $clock = new Clock; $now = $clock->now(); // return an instance of PointInTime echo $now->toString(); //2016-10-11T12:17:30+02:00 $epoch = $clock->at('1970-01-01T00:00:00.000000Z'); // Maybe<PointInTime>
Here we reference 2 points in time, the first is the exact moment we call now
down to the millisecond and the second one is the epoch time (you can verify it via $epoch->milliseconds()
that returns 0
).
The method at()
accepts any string that is allowed by \DateTimeImmutable
.
Timezones
Say you want to work only with Europe/Paris
timezone in your app but don't know if every environment will have the same configuration (like between your machine and the CI), you can enforce the timezone you'll work with like so:
use Innmind\TimeContinuum\Earth\{ Clock, Timezone\Europe\Paris, }; $clock = new Clock(new Paris); echo $clock->now()->timezone()->toString(); //+02:00 (when DST applied), otherwise +01:00
And if you're given a point in time via a method parameter but don't know its timezone, you can change it via:
use Innmind\TimeContinuum\{ PointInTime, Earth\Timezone\Europe\Paris }; function foo(PointInTime $point) { $point = $point->changeTimezone(new Paris); }
Note: Don't forget to reassign into a variable as all objects are immutable.
Time travel
use Innmind\TimeContinuum\Earth\Period\{ Year, Month, Minute, Millisecond, }; $point = $clock ->now() ->goBack( (new Year(1)) ->add(new Month(2)) ->add(new Minute(24)) ->add(new Millisecond(500)) );
Here we go back 1 year, 2 months, 24 minutes and half a second back in time. The same objects are used to goForward()
.
Note: Objects from the Innmind\TimeContinuum\Earth\Period
namespace will convert values if you go out of the component boundary. For example, new Millisecond(121500)
will result in this: milliseconds() === 500
, seconds() === 1
and minutes() === 2
.
To ease some common operations this lib contains helpers such as EndOfDay
to be used like this:
use Innmind\TimeContinuum\Earth\Move\EndOfDay; $endOfDay = new EndOfDay; $endOfDay($clock->now()); // will return 2018-04-28 23:59:59.999
Check all the helpers to help you travel in time.
Elapsed period
Sometimes we want to know how long a task takes in our code and we end up using microtime(true) * 1000
. Here you can have a more elegant way of doing it (and one that is unit test friendly)
$start = $clock->now(); //run some code... $duration = $clock ->now() ->elapsedSince($start) ->milliseconds();
And if you want a more comprehensible duration if it's above the second, you can reuse new Millisecond($duration)
.
Date formatting
In order to format a PointInTime
you need to create a class implementing Format
. This is done so you can make sure a date format will always have a name (and prevent you from putting magic strings everywhere in your codebase).
All formats described as \DateTime
constants are already available as formats here.
Important: here ISO8601
truely respect the ISO format as opposed to \DateTime::ISO8601
.