stratadox/clock

v0.2 2021-03-18 09:10 UTC

README

创建日期时间对象的工厂。

Build Status Coverage Status Scrutinizer Code Quality

是什么

正如其名所暗示的那样:这是一个时钟,用于指示当前时间。

由于它产生DateTime对象,因此这个时钟在某种程度上是特殊的,因为它还可以读取日期。

Just a clock, really.

为什么

  • 一旦你在代码中使用“未掺杂”的日期时间对象,你为其编写的任何测试都立即面临风险,因为如果在new DateTime和你的断言之间有一点点时间差,测试就会失败。
  • 在客户端代码中实例化new DateTimenew DateTimeImmutable是一个静态调用。这引入了耦合并降低了可测试性。对于date_create()等,这显然加倍。
  • 从时钟获取时间比每次想知道时间晚了多久就实例化一个新的瞬间要自然得多。

安装

使用composer require stratadox/clock进行安装

示例

时钟示例

需要知道时间的服务

<?php
namespace Your\Project;

use Stratadox\Clock\Clock;

class SomeFactory
{
    private $clock;

    public function __construct(Clock $clock)
    {
        $this->clock = $clock;
    }

    public function createSomething(): Something
    {
        return new Something($this->clock->now());
    }
}

class Something
{
    private $creationDate;

    public function __construct(\DateTimeInterface $creationDate)
    {
        $this->creationDate = $creationDate;
    }

    public function creationDate(): \DateTimeInterface
    {
        return $this->creationDate;
    }
}

可回滚时钟示例

需要回滚或快进时钟的服务

<?php
namespace Your\Project;

use Stratadox\Clock\RewindableClock;

class Scheduler
{
    private $clock;

    public function __construct(RewindableClock $clock)
    {
        $this->clock = $clock;
    }

    public function scheduleForTheNextThreeHours(): Schedule
    {
        return new Schedule(
            new Activity($this->clock->now()),
            new Activity($this->clock->fastForward(new \DateInterval('PT1H'))->now()),
            new Activity($this->clock->fastForward(new \DateInterval('PT2H'))->now())
        );
    }

    public function whenDoIWantThisOnMyDesk(): \DateTimeInterface
    {
        return $this->clock->rewind(new \DateInterval('P1D'))->now();
    }
}

选择时钟

默认实现是DateTimeClock。每次调用now时,它都会产生一个新的DateTimeImmutable对象。

如果日期时间对象需要传递到具有DateTime类型提示的东西,或者依赖于可变日期时间对象,则最好解决该问题。例如,可以将DateTime提示替换为DateTimeIterfaceDateTimeImmutable,或者传递RewindableClock。在没有这种选择的情况下,可以使用DateTimeMutableClock时钟。

如果时间区域在你的上下文中很重要,还有TimeZoneAwareClock,它将时间区域作为构造函数参数。

要防止时钟在运行其他代码时滴答作响,你的测试可以实例化和注入一个UnmovingClock

在服务定义中

<?php
use Stratadox\Clock\Clock;
use Stratadox\Clock\DateTimeClock;

$container->set(Clock::class, function () {
    return DateTimeClock::create();
});

在单元测试中

<?php
use Your\Project\SomeFactory;
use PHPUnit\Framework\TestCase;
use Stratadox\Clock\UnmovingClock;

class SomethingTest extends TestCase
{
    public function testCreatingSomething(): void
    {
        $testTime = new DateTimeImmutable('1-1-1960');
        $factory = new SomeFactory(
            UnmovingClock::standingStillAt($testTime)
        );

        $something = $factory->createSomething();

        $this->assertEquals($testTime, $something->creationDate());
    }
}

当时钟需要能够回滚或快进时,使用RewindableDateTimeClock实现。

在服务定义中

<?php
use Stratadox\Clock\RewindableClock;
use Stratadox\Clock\RewindableDateTimeClock;

$container->set(RewindableClock::class, function () {
    return RewindableDateTimeClock::create();
});

在单元测试中

<?php
use Your\Project\Scheduler;
use PHPUnit\Framework\TestCase;
use Stratadox\Clock\RewindableDateTimeClock;
use Stratadox\Clock\UnmovingClock;

class SchedulerTest extends TestCase
{
    public function testWhenItShouldBeOnTheirDesk(): void
    {
        $scheduler = new Scheduler(
            RewindableDateTimeClock::using(UnmovingClock::standingStillAt(
                new DateTimeImmutable('16-5-1991')
            ))
        );

        $this->assertEquals(
            new DateTimeImmutable('15-5-1991'),
            $scheduler->whenDoIWantThisOnMyDesk()
        );
    }
}

以下是一个概述,说明何时使用哪个时钟

请注意,可回滚时钟可以与任何其他时钟结合使用,以生成特定时间区域中的回滚可变日期时间对象。