twindigital / clock
1.0.0
2024-03-08 16:03 UTC
Requires
- php: >=7.2
Requires (Dev)
- php-coveralls/php-coveralls: ^2.1
- phpstan/phpstan: ^0.11.12
- phpunit/phpunit: ^8.2
- roave/security-advisories: dev-master
This package is not auto-updated.
Last update: 2024-09-27 12:37:29 UTC
README
创建日期时间对象的工厂。
是什么
正如其名所示,这实际上就是一个时钟,用于指示当前的时间。
由于它产生 DateTime 对象,这个时钟在某种意义上也是特别的,因为它还可以读取日期。
为什么
- 一旦你在代码中使用“未经过滤”的日期时间对象,任何为其编写的测试都立即面临失败的风险,因为如果在
new DateTime
和你的断言之间存在一点时间差,测试就会失败。 - 在客户端代码中实例化
new DateTime
或new 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
提示替换为 DateTimeIterface
或 DateTimeImmutable
,或者传递一个 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()
);
}
}
以下是何时使用哪种时钟的概述
时钟 | 何时使用 |
---|---|
DateTimeClock | 在大多数情况下 |
DateTimeMutableClock | 当你不能使用 DateTimeImmutable 时 |
TimeZoneAwareClock | 当默认时区不够用时 |
TimeZoneAwareMutableClock | 当上述两个原因都适用时 |
UnmovingClock | 在测试期间 |
RewindableDateTimeClock | 如果需要将时钟设置回或前进 |
请注意,可倒退时钟可以与任何其他时钟结合使用,例如,在特定时区产生倒退的可变日期时间对象。