编程 PHP 8.6 的 Time\Duration:让「一段长度」和日历语义分开

2026-11-15 21:01:18

PHP 8.6 的 Time\Duration:让「一段长度」和日历语义分开

PHP 8.6 新增了 Time\Duration,它是一个 final readonly 类,用来表示秒表式的、固定长度的时间,精度到纳秒。它提供按单位构造的工厂方法、四则运算方法,以及比较支持。

基本用法

use Time\Duration;

$oneSecond = Duration::fromSeconds(1);
$halfSecond = $oneSecond->divideBy(2);
$total = $oneSecond->add($halfSecond);

$delay = Duration::fromMilliseconds(100)->multiplyBy(2 ** $attempt);

$total > $delay; // 比较运算符可用

Duration 是不可变对象,可以直接用比较运算符比较大小。它也可以从 ISO 8601 duration 字符串构造。设计目标,是让它成为一个共享类型:原本核心函数和新的 polling API 只能接收散落的 int/float 参数,现在可以统一接收 Duration。

为什么还需要另一个时长类型

PHP 的 DateTime 扩展有一处短板:它提供了 DateInterval 用于按指定间隔推算新日期,但 DateInterval 只适用于日历日期,不适用于一般的时间值。

Time\Duration 表示的是流逝时长的固定值,比如一个超时时间,精度为纳秒。和 DateInterval 的关键差别在于:Duration 不包含「天」「月」这类日历单位,所以它的长度是无歧义的。

P1M 这类写法本身就是歧义来源:一个月是 28 天、29 天、30 天还是 31 天,取决于它落在哪个日历位置上。这种不确定性对于推算日期是必要的,但对于「等 200 毫秒后重试」这类场景则完全不合适。

类提供的能力

  • 工厂方法:Time\Duration::fromSeconds()、Time\Duration::fromMilliseconds()、Time\Duration::fromIso8601DurationString()
  • 运算:Time\Duration::add()、Time\Duration::sub()、Time\Duration::multiplyBy()、Time\Duration::divideBy()
  • 符号变换:Time\Duration::negate()、Time\Duration::absolute()
  • 排序回调:Time\Duration::compare()

边界情况

当 Duration 超出可表示范围(约 292 年)时,会抛出 Time\TimeException。当传入的 ISO 8601 duration 字符串非法时,同样抛出 Time\TimeException。292 年这个上限来自纳秒精度下的整数位宽,因此它是硬性上限,而不是可配置项。

取舍:什么时候仍然使用 DateInterval

判断标准可以简化成一句话:这段长度是否依赖于日历。

  • 重试退避、超时、限流窗口、缓存 TTL —— 这些都是纯流逝时间,用 Duration。没有「月」「日」单位,就不用解释一个月的含义。
  • 「下个月同一天」「三个工作日之后」「每年提醒」 —— 这些仍然使用 DateInterval,因为答案确实取决于起始日期和时区规则。

把两者混在同一个类型里,代价就是任何一次「加一个月」的运算都要带着起始时间做上下文,而 Duration 通过砍掉日历单位把这件事排除掉了。

指数退避示例

把退避时间表示为 Duration 之后,第 $attempt 次重试的等待量直接写成乘法:

use Time\Duration;

$delay = Duration::fromMilliseconds(100)->multiplyBy(2 ** $attempt);

// $delay 是 Duration,可直接传给接受该类型的 API,
// 也可与其它 Duration 做比较,无需在调用点反复换算单位

基准值 100 ms 是 Duration,multiplyBy(2 ** $attempt) 返回新的 Duration,全程不出现裸数字,单位换算收敛在构造那一行。

版本状态

PHP 8.6 计划于 2026 年 11 月 19 日 GA。当前最新预发布版为 8.6.0RC7(2026 年 11 月 12 日)。本文涉及的行为描述基于该预发布阶段,尚未在生产环境实测;RC 到 GA 之间若 API 有调整,以最终发布说明为准。

复制全文 生成海报 PHP 时间处理 版本特性

推荐文章

程序员茄子在线接单