Skip to content

Commit

Permalink
feat: Clock component
Browse files Browse the repository at this point in the history
  • Loading branch information
devnix committed Nov 4, 2024
1 parent 77af041 commit 47a5d61
Show file tree
Hide file tree
Showing 7 changed files with 191 additions and 2 deletions.
3 changes: 2 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@
"vimeo/psalm": "^5.23.1",
"php-standard-library/psalm-plugin": "^2.3.0",
"php-coveralls/php-coveralls": "^2.7.0",
"roave/infection-static-analysis-plugin": "^1.35.0"
"roave/infection-static-analysis-plugin": "^1.35.0",
"psr/clock": "^1.0"
},
"autoload": {
"psr-4": {
Expand Down
50 changes: 49 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions src/Psl/Clock/ClockInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php

declare(strict_types=1);

namespace Psl\Clock;

use Psl\DateTime;

interface ClockInterface
{
public function now(): DateTime\DateTimeInterface;
}
24 changes: 24 additions & 0 deletions src/Psl/Clock/FrozenClock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

declare(strict_types=1);

namespace Psl\Clock;

use Psl\DateTime;

final class FrozenClock implements ClockInterface
{
public function __construct(private DateTime\DateTime $dateTime)
{
}

public function synchronize(DateTime\DateTime $dateTime): void
{
$this->dateTime = $dateTime;
}

public function now(): DateTime\DateTimeInterface
{
return $this->dateTime;
}
}
30 changes: 30 additions & 0 deletions src/Psl/Clock/PsrClock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Psl\Clock;

use Psl\DateTime;
use Psr\Clock\ClockInterface as PsrClockInterface;
use function Psl\invariant;

final class PsrClock implements ClockInterface
{
public function __construct(private PsrClockInterface $psrClock)
{
}

public function now(): DateTime\DateTimeInterface
{
$nativeDateTime = $this->psrClock->now();

$timestamp = DateTime\Timestamp::fromParts($nativeDateTime->getTimestamp());

$timezone = $nativeDateTime->getTimezone();
invariant($timezone !== false, 'Could not get the timezone object.');

$timezone = DateTime\Timezone::from($timezone->getName());

return DateTime\DateTime::fromTimestamp($timestamp, $timezone);
}
}
30 changes: 30 additions & 0 deletions src/Psl/Clock/SystemClock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

declare(strict_types=1);

namespace Psl\Clock;

use Psl\Clock\ClockInterface;
use Psl\DateTime;

final readonly class SystemClock implements ClockInterface
{
private function __construct(private DateTime\Timezone $timezone)
{
}

public static function fromTimezone(DateTime\Timezone $timezone): self
{
return new self($timezone);
}

public static function fromSystemTimezone(): self
{
return new self(DateTime\Timezone::from(date_default_timezone_get()));
}

public function now(): DateTime\DateTimeInterface
{
return DateTime\DateTime::now($this->timezone);
}
}
44 changes: 44 additions & 0 deletions tests/unit/Clock/PsrClockTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
<?php

declare(strict_types=1);

namespace Psl\Tests\Unit\Clock;

use Psl\Clock\PsrClock;
use PHPUnit\Framework;
use Psr\Clock\ClockInterface as PsrClockInterface;
use Psl\DateTime;

final class PsrClockTest extends Framework\TestCase
{
public function testNow(): void
{
$clock = new PsrClock(
new FixedPsrClock(
new \DateTimeImmutable('2020-01-01 00:00:00', new \DateTimeZone('Africa/Tunis'))
)
);

self::assertTrue(
$clock->now()->equalsIncludingTimezone(
DateTime\DateTime::parse(
'2020-01-01 00:00:00',
DateTime\FormatPattern::SqlDateTime,
DateTime\Timezone::AfricaTunis,
)
)
);
}
}

class FixedPsrClock implements PsrClockInterface
{
public function __construct(private readonly \DateTimeImmutable $now)
{
}

public function now(): \DateTimeImmutable
{
return $this->now;
}
}

0 comments on commit 47a5d61

Please sign in to comment.