alex-patterson-webdev / date-time
PHP的DateTime工厂组件
Requires
- php: >=8.1
- psr/clock: ^1.0.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.6.0
- phpspec/prophecy: ^1.15.0
- phpstan/phpstan: ^1.4.8
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
Provides
This package is auto-updated.
Last update: 2024-09-11 04:02:55 UTC
README
Arp\DateTime
关于
该库提供了PSR-20 Clock ClockInterface
的实现以及一些工厂类,这些工厂类抽象了PHP原生日时间对象的创建。
安装
通过composer安装。
require alex-patterson-webdev/date-time ^0.6
理论
通过在简单接口集合后抽象日期时间的创建,我们可以让开发者将日期时间创建视为一种服务。可以使用Arp\DateTime\DateTimeFactory
作为任何通常需要使用new \DateTime()
的代码的替代。
考虑一个示例方法UserService::updateLastLoginDate()
;该方法是用来更新用户的最后登录日期为当前日期和时间。
class UserService
{
public function updateLastLoginDate($user)
{
$user->setLastLoginDate(new \DateTime());
}
}
虽然这个方法简单,但在单元测试中很难断言'当前时间'的值。作为替代,我们可以将此示例更新为包含DateTimeFactory
,这将抽象\DateTime
对象的创建。
class UserService
{
private DateTimeFactoryInterface $dateTimeFactory;
public function __construct(DateTimeFactoryInterface $dateTimeFactory)
{
$this->dateTimeFactory = $dateTimeFactory;
}
public function updateLastLoginDate($user)
{
$user->setLastLoginDate($this->dateTimeFactory->createDateTime());
}
}
这种方法有几个显著的优点
DateTimeFactoryInterface
为所有\DateTime
对象创建提供了一个抽象。- 由于现在可以模拟
$this->dateTimeFactory->createDateTime()
的返回值,单元测试和断言日期时间值变得非常容易。 - 当无法创建日期对象时,而不是返回布尔值
false
,工厂类将抛出DateTimeException
。
DateTimeFactoryInterface
DateTimeFactoryInterface
公开了两个公共方法,createDateTime()
和createFromFormat()
。方法签名与PHP \DateTime
方法相似。
interface DateTimeFactoryInterface
{
/**
* @throws DateTimeFactoryException
*/
public function createDateTime(?string $spec = null, $timeZone = null): \DateTimeInterface;
/**
* @throws DateTimeFactoryException
*/
public function createFromFormat(string $format, string $spec, $timeZone = null): \DateTimeInterface;
}
createDateTime()
方法可以替代\DateTime::__construct的使用。而createFromFormat()
方法可以替代\DateTime::createFromFormat()的使用。
然而,有一些差异需要考虑。
- 接口中的方法被定义为非静态的,并且需要工厂实例来调用。
- 如果无法创建
\DateTime
实例,将抛出DateTimeFactoryException
。 createDateTime()
方法的$spec
参数可以接受null
。传递null
相当于使用当前日期和时间,即now
。$timeZone
可以是字符串或\DateTimeZone
实例。如果提供了一个受支持的DateTimeZone
字符串,内部将创建\DateTimeZone
实例;否则将抛出DateTimeFactoryException
。
实现
该软件包提供了两个默认的DateTimeFactoryInterface
实现。
DateTimeFactory
可以用来创建\DateTime
实例。DateTimeImmutableFactory
可以用来创建\DateTimeImmutible
实例
由于这两个类都实现了DateTimeFactoryInterface
,因此它们可以以相同的方式使用。
$dateTimeFactory = new \Arp\DateTime\DateTimeFactory();
$dateTimeImmutableFactory = new \Arp\DateTime\DateTimeImmutableFactory();
try {
/** @var \DateTime $dateTime **/
$dateTime = $dateTimeFactory->createDateTime();
/** @var \DateTimeImmutable $dateTimeImmutable **/
$dateTimeImmutable = $dateTimeImmutableFactory->createDateTime();
} catch (\DateTimeFactoryException $e) {
// if the date creation fails
}
DateTimeZoneFactory
可以使用任何实现了Arp\DateTime\DateTimeZoneFactoryInterface
的类来创建\DateTimeZone
实例。
/*
* @throws DateTimeZoneFactoryException
*/
public function createDateTimeZone(string $spec): \DateTimeZone;
接口的默认实现是 Arp\DateTime\DateTimeZoneFactory
。
$dateTimeZoneFactory = new \Arp\DateTime\DateTimeZoneFactory();
try {
/** @var \DateTimeZone $dateTimeZone **/
$dateTimeZone = $dateTimeZoneFactory->createDateTimeZone('UTC');
} catch (\DateTimeZoneFactoryException $e) {
// The \DateTimeZone() could not be created
}
PSR-20 时钟接口
使用PSR标准通过创建一种访问当前时间的方式,为实施项目提供与其他包之间的互操作性。
该包提供了一系列PSR-20 时钟接口的实现。
Arp\DateTime\Psr\Clock
是一个默认实现,可以提供所需的DateTimeZone。Arp\DateTime\Psr\SystemClock
是一个实现PSR\Clock\ClockInterface的实例,它将始终使用配置的系统时区提供当前时间。Arp\DateTime\Psr\FixedClock
是一个实现PSR\Clock\ClockInterface的实例,它将始终返回一个固定的\DateTimeImmutable
;这在测试中可能很有用。
示例用法
use Arp\DateTime\DateTimeImmutableFactory;
use Arp\DateTime\Psr\SystemClock;
// Fetch the current time using the UTC timezone
$clock = new Clock(new DateTimeImmutableFactory(), 'UTC');
$utcTime = $clock->now();
// Fetch the current time using the systems configured timezone
$clock = new SystemClock(new DateTimeImmutableFactory());
$systemTime = $clock->now();
// Calls to FixedClock::now() will always return the same time provided in the constructor
$clock = new FixedClock(new \DateTimeImmutable());
$fixedTime = $clock->now();
单元测试
可以通过从应用程序根目录使用PHPUnit执行单元测试。
php vendor/bin/phpunit