diff --git a/CHANGELOG.md b/CHANGELOG.md index 4250c46..c210b79 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0. - `PsrToOrisaiClockAdapter` - makes any PSR clock compatible with `Orisai\Clock\Clock` - `SymfonyToOrisaiClockAdapter` - makes any symfony/clock compatible with `Orisai\Clock\Clock` - `ClockAdapterFactory` - chooses best supported adapter for `Orisai\Clock\Clock` compatibility +- `FrozenClock` - accepts `DateTimeInterface` as the initial time ### Changed diff --git a/docs/README.md b/docs/README.md index 46c35eb..3dfffc2 100644 --- a/docs/README.md +++ b/docs/README.md @@ -130,6 +130,17 @@ use DateTimeZone; $clock = new FrozenClock(0, new DateTimeZone('UTC')); ``` +You can also create clock from datetime + +```php +use DateTime; +use DateTimeImmutable; + +$clock = new FrozenClock(new DateTimeImmutable()); +// or +$clock = new FrozenClock(new DateTime()); +``` + [Sleeping](#sleep) does not put thread to sleep but just moves timestamp of clock's internal `DateTimeImmutable`. ### Measurement clock diff --git a/src/FrozenClock.php b/src/FrozenClock.php index 0578fc8..a7e5e32 100644 --- a/src/FrozenClock.php +++ b/src/FrozenClock.php @@ -2,7 +2,9 @@ namespace Orisai\Clock; +use DateTime; use DateTimeImmutable; +use DateTimeInterface; use DateTimeZone; use function date_default_timezone_get; use function floor; @@ -16,13 +18,22 @@ final class FrozenClock implements Clock private DateTimeImmutable $dt; - public function __construct(float $timestamp, ?DateTimeZone $timeZone = null) + /** + * @param float|DateTimeInterface $timestamp + */ + public function __construct($timestamp, ?DateTimeZone $timeZone = null) { - [$seconds, $microseconds] = $this->getParts($timestamp); + if ($timestamp instanceof DateTime) { + $dt = DateTimeImmutable::createFromMutable($timestamp); + } elseif ($timestamp instanceof DateTimeImmutable) { + $dt = $timestamp; + } else { + [$seconds, $microseconds] = $this->getParts($timestamp); + $dt = DateTimeImmutable::createFromFormat('U', (string) $seconds) + ->modify("+$microseconds microsecond"); + } - $this->dt = DateTimeImmutable::createFromFormat('U', (string) $seconds) - ->setTimezone($timeZone ?? new DateTimeZone(date_default_timezone_get())) - ->modify("+$microseconds microsecond"); + $this->dt = $dt->setTimezone($timeZone ?? new DateTimeZone(date_default_timezone_get())); } public function now(): DateTimeImmutable diff --git a/tests/Unit/FrozenClockTest.php b/tests/Unit/FrozenClockTest.php index b3d2a3d..7e4d840 100644 --- a/tests/Unit/FrozenClockTest.php +++ b/tests/Unit/FrozenClockTest.php @@ -2,7 +2,11 @@ namespace Tests\Orisai\Clock\Unit; +use DateTime; +use DateTimeImmutable; +use DateTimeInterface; use DateTimeZone; +use Generator; use Orisai\Clock\FrozenClock; use PHPUnit\Framework\TestCase; use function date_default_timezone_get; @@ -40,6 +44,35 @@ public function testFrozenTime(): void self::assertSame('1.000000', $now); } + /** + * @param int|DateTimeInterface $datetime + * + * @dataProvider provideTimestampVariants + */ + public function testTimestampVariants($datetime, int $timestamp): void + { + $clock = new FrozenClock($datetime); + self::assertSame($timestamp, $clock->now()->getTimestamp()); + } + + public function provideTimestampVariants(): Generator + { + yield [ + 1, + 1, + ]; + + yield [ + DateTimeImmutable::createFromFormat('U', '1'), + 1, + ]; + + yield [ + DateTime::createFromFormat('U', '1'), + 1, + ]; + } + public function testTimeDoesNotChange(): void { $clock = new FrozenClock(1); diff --git a/tools/phpstan.baseline.neon b/tools/phpstan.baseline.neon index c5e4667..a4adb95 100644 --- a/tools/phpstan.baseline.neon +++ b/tools/phpstan.baseline.neon @@ -1,13 +1,13 @@ parameters: ignoreErrors: - - message: "#^Cannot call method setTimezone\\(\\) on DateTimeImmutable\\|false\\.$#" + message: "#^Cannot call method modify\\(\\) on DateTimeImmutable\\|false\\.$#" count: 1 path: ../src/FrozenClock.php - message: "#^Property Orisai\\\\Clock\\\\FrozenClock\\:\\:\\$dt \\(DateTimeImmutable\\) does not accept \\(DateTimeImmutable\\|false\\)\\.$#" - count: 5 + count: 4 path: ../src/FrozenClock.php - @@ -20,6 +20,11 @@ parameters: count: 1 path: ../src/MeasurementClock.php + - + message: "#^Parameter \\#1 \\$now of class Symfony\\\\Component\\\\Clock\\\\MockClock constructor expects DateTimeImmutable\\|string, DateTimeImmutable\\|false given\\.$#" + count: 2 + path: ../tests/Unit/Adapter/SymfonyToOrisaiClockAdapterTest.php + - message: """ #^Call to deprecated method move\\(\\) of class Orisai\\\\Clock\\\\FrozenClock\\: @@ -27,8 +32,3 @@ parameters: """ count: 9 path: ../tests/Unit/FrozenClockTest.php - - - - message: "#^Parameter \\#1 \\$now of class Symfony\\\\Component\\\\Clock\\\\MockClock constructor expects DateTimeImmutable\\|string, DateTimeImmutable\\|false given\\.$#" - count: 2 - path: ../tests/Unit/Adapter/SymfonyToOrisaiClockAdapterTest.php