96 lines
3.5 KiB
PHP
96 lines
3.5 KiB
PHP
<?php
|
|
|
|
declare(strict_types=1);
|
|
|
|
namespace Tests\Unit\Shared\Time;
|
|
|
|
use Psr\Clock\ClockInterface;
|
|
use Shared\Time\Clock;
|
|
use Shared\Time\FrozenClock;
|
|
use Shared\Time\SystemClock;
|
|
use Shared\Time\SystemUtcClock;
|
|
use Shared\Time\Utc;
|
|
|
|
covers(
|
|
SystemClock::class,
|
|
SystemUtcClock::class,
|
|
FrozenClock::class,
|
|
Utc::class,
|
|
);
|
|
|
|
afterEach(function (): void {
|
|
Utc::restore();
|
|
});
|
|
|
|
describe('PSR-20 UTC Clock Unit Tests', function (): void {
|
|
it('implements Psr ClockInterface and Clock contract with configured timezone', function (): void {
|
|
// GIVEN
|
|
$parisClock = new SystemClock(new \DateTimeZone('Europe/Paris'));
|
|
$utcClock = new SystemUtcClock();
|
|
|
|
// WHEN
|
|
$parisNow = $parisClock->now();
|
|
$utcNow = $utcClock->now();
|
|
|
|
// THEN
|
|
expect($parisClock)->toBeInstanceOf(ClockInterface::class)
|
|
->and($parisClock)->toBeInstanceOf(Clock::class)
|
|
->and($parisNow->getTimezone()->getName())->toBe('Europe/Paris')
|
|
->and($parisClock->timezone()->getName())->toBe('Europe/Paris')
|
|
->and($utcNow->getTimezone()->getName())->toBe('UTC');
|
|
});
|
|
|
|
it('parses date strings and normalizes to UTC with SystemUtcClock', function (): void {
|
|
// GIVEN
|
|
$clock = new SystemUtcClock();
|
|
|
|
// WHEN
|
|
$utcTime = $clock->parse('2026-08-21T15:00:00+02:00');
|
|
$startOfDay = $clock->startOfDay('2026-08-21');
|
|
$endOfDay = $clock->endOfDay('2026-08-21');
|
|
$isoString = $clock->toIso8601($utcTime);
|
|
|
|
// THEN
|
|
expect($utcTime->getTimezone()->getName())->toBe('UTC')
|
|
->and($utcTime->format('Y-m-d H:i:s'))->toBe('2026-08-21 13:00:00')
|
|
->and($startOfDay->format('Y-m-d H:i:s'))->toBe('2026-08-21 00:00:00')
|
|
->and($endOfDay->format('Y-m-d H:i:s.u'))->toBe('2026-08-21 23:59:59.999999')
|
|
->and($isoString)->toBe('2026-08-21T13:00:00+00:00');
|
|
});
|
|
|
|
it('allows freezing and manipulating time with FrozenClock', function (): void {
|
|
// GIVEN
|
|
$fixedTime = new \DateTimeImmutable('2026-08-21 10:00:00', new \DateTimeZone('UTC'));
|
|
$frozenClock = new FrozenClock($fixedTime);
|
|
|
|
// THEN
|
|
expect($frozenClock->now()->format('Y-m-d H:i:s'))->toBe('2026-08-21 10:00:00');
|
|
|
|
// WHEN
|
|
$frozenClock->setTo('2026-12-31 23:59:59');
|
|
|
|
// THEN
|
|
expect($frozenClock->now()->format('Y-m-d H:i:s'))->toBe('2026-12-31 23:59:59')
|
|
->and($frozenClock->now()->getTimezone()->getName())->toBe('UTC');
|
|
});
|
|
|
|
it('provides centralized static access through Utc facade', function (): void {
|
|
// GIVEN
|
|
$frozen = Utc::freeze(new \DateTimeImmutable('2026-08-21 14:00:00', new \DateTimeZone('UTC')));
|
|
|
|
// THEN
|
|
expect(Utc::now()->format('Y-m-d H:i:s'))->toBe('2026-08-21 14:00:00')
|
|
->and(Utc::parse('2026-08-21 12:00:00')->format('Y-m-d H:i:s'))->toBe('2026-08-21 12:00:00')
|
|
->and(Utc::startOfDay('2026-08-21')->format('Y-m-d H:i:s'))->toBe('2026-08-21 00:00:00')
|
|
->and(Utc::endOfDay('2026-08-21')->format('Y-m-d H:i:s'))->toBe('2026-08-21 23:59:59')
|
|
->and(Utc::toRfc3339('2026-08-21 14:00:00'))->toBe('2026-08-21T14:00:00+00:00')
|
|
->and(Utc::toNullableRfc3339(null))->toBeNull()
|
|
->and(Utc::toNullableRfc3339('2026-08-21 14:00:00'))->toBe('2026-08-21T14:00:00+00:00');
|
|
|
|
// WHEN
|
|
Utc::restore();
|
|
|
|
// THEN
|
|
expect(Utc::getClock())->toBeInstanceOf(SystemUtcClock::class);
|
|
});
|
|
});
|