flying/日期

支持调整当前时间的日期生成器

v2.0.0 2023-11-04 16:58 UTC

This package is auto-updated.

Last update: 2024-09-04 18:51:27 UTC


README

DateTime 生成器,支持调整当前时间。

目的

该库的主要目的是在无需调整其代码的情况下(除了切换到使用库本身来创建应用程序中的日期外),帮助测试应用程序在时间敏感场景中。

对于单元测试,测试时间敏感场景相对简单,但对于功能测试来说则要困难得多。当然,有许多解决方案

该库旨在将所需的更改数量保持与其他解决方案相当的水平。下面列出了所需的 代码更新,基本上仅限于将 \DateTime 构造函数方法更改为调用不同类的静态方法。它还简化了测试用例,当代码执行花费了一些时间,并且这种时间变化被以某种方式使用时(例如性能跟踪)。

一般信息

整个 API 都以单个 \Flying\Date\Date 类的形式公开。API 提供了一组静态方法,以确保可以从代码的任何部分访问它们,而无需引入任何类型的附加依赖。

生成的日期对象限于 \DateTimeImmutable。来自 PSR-20 的即将推出的 ClockInterface 也仅提供不可变日期。

主要 API 方法 - nowfrom 返回 \DateTimeImmutable 实例,可以通过使用 adjust 方法提供时间偏移量来调整其值,以相对于实际当前时间。

在应用程序中使用

为了利用时间偏移功能,需要更新创建新的 \DateTime\DateTimeInterval 对象的代码部分。

要获取 \DateTime 对象,需要将获取到的 \DateTimeInterval 对象转换为 \DateTime 对象

$mutableDateTime = \DateTime::createFromImmutable($immutableDateTime); 

创建当前时间和默认时区的对象

  • 之前: new \DateTimeImmutable()
  • 之后: \Flying\Date\Date::now()

创建任意时间和/或时区的对象

从字符串创建

  • 之前: new \DateTimeImmutable('2022-08-01', new \DateTimeZone('UTC'))
  • 之后: \Flying\Date\Date::from('2022-08-01', 'UTC')

从格式创建

  • 之前: \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, 2022-08-01T12:23:34Z')
  • 之后: \Flying\Date\Date::fromFormat(\DateTimeInterface::ATOM, '2022-08-01T12:23:34Z')

在测试中使用

为了测试在不同时间点上的应用程序行为,需要做两件事

  1. 通过调用 \Flying\Date\Date::adjust() 来提供日期调整值,传入代表新目标日期的 \DateTimeInterface 或定义相对于当前时间的时移的 \DateInterval。不带参数调用 adjust() 将移除日期调整。
  2. 通过调用 \Flying\Date\Date::allowAdjustment(true) 来启用日期调整。

重要! 在您的应用程序代码中绝不应该使用日期调整,仅限在测试中使用!在应用程序代码中使用它可能会导致意外的行为!

即使在测试中,也应该将此功能的限制在需要日期调整功能的测试中,并在测试后禁用它。

使用属性简化配置

为了简化库的使用并确保在测试中正确启用/禁用日期调整功能,可以使用 AdjustableDate PHP 属性。

要启用属性,您需要编辑您的 PHPUnit 配置(phpunit.xml)并添加测试扩展。

<extensions>
   <!-- ... other extensions ... -->
   <bootstrap class="Flying\Date\PHPUnit\Extension\DateExtension"/>
</extensions>

然后,对于需要使用可调整日期功能的测试类或(最好是)测试方法,您需要添加 #[AdjustableDate] 属性。它接受可选的配置参数。

  • bool $enabled - 用于控制可调整日期功能的默认状态(默认为 true
  • \DateTimeZone|string|null $timezone - 用于定义默认时区

关于日期调整中的微秒的说明

对于由 nowfrom 方法生成的时移间隔和调整日期,结果日期的微秒部分将被强制设置为零。未进行日期调整生成的日期对象不受影响。

这应该是安全的,因为日期调整仅用于测试。在小于一秒的间隔上进行时间位移的微秒精度测试,使用 usleep() 更可靠。对于更大的间隔,包括微秒可能会引入整个秒的差异,这可能导致测试偶尔失败。

API 方法

now

签名

\Flying\Date\Date::now(): \DateTimeImmutable

提供当前日期的日期对象。使用通过 setTimezone() 定义或 PHP 默认时区的时区。

如果启用了日期调整,则返回的日期将根据定义的时移间隔进行调整。

from

签名

\Flying\Date\Date::from(\DateTimeInterface|\DateInterval|string $date, \DateTimeZone|string|null $timezone = null): \DateTimeImmutable

根据提供的日期和时区信息创建给定任意时间点的日期对象。使用给定的时区,通过 setTimezone() 定义的时区或 PHP 默认时区。允许将有效时区名称作为时区值传递。

如果启用了日期调整,则返回的日期将根据定义的时移间隔进行调整。

fromFormat

签名

\Flying\Date\Date::fromFormat(string $format, string $datetime, \DateTimeZone|string|null $timezone = null): \DateTimeImmutable|bool

使用给定的格式和时区信息创建给定日期字符串的日期对象。使用给定的时区,通过 setTimezone() 定义的时区或 PHP 默认时区。允许将有效时区名称作为时区值传递。

如果启用了日期调整,则返回的日期将根据定义的时移间隔进行调整。

getTimezone

签名

\Flying\Date\Date::getTimezone(): \DateTimeZone

获取用于创建日期对象的时区。

setTimezone

签名

\Flying\Date\Date::setTimezone(\DateTimeZone|string|null $timezone = null): void

定义(或重置)用于创建日期对象的时区。允许将有效时区名称作为值传递。

adjust

签名

\Flying\Date\Date::adjust(\DateInterval|\DateTimeInterface|string|null $adjustment = null): void

定义(或重置)用于在创建日期对象时调整日期的时移间隔。允许通过传递 \DateTimeInterface 实例定义绝对时间点或通过传递 \DateInterval 对象定义相对于当前时间点的时移。

还可以传递 日期格式日期间隔 定义。

getAdjustment

签名

\Flying\Date\Date::getAdjustment(): ?\DateInterval

返回当前定义的时间偏移间隔,该间隔用于在创建日期对象时调整日期。

allowAdjustment

签名

\Flying\Date\Date::allowAdjustment(bool $status): void

允许控制日期调整功能的状态。

isAdjustmentAllowed

签名

\Flying\Date\Date::isAdjustmentAllowed(): bool

返回日期调整功能当前的状态。

许可证

该库遵从MIT许可证