什么是 InteractsWithTime
Illuminate\Support\InteractsWithTime 是把时间、延迟、耗时计算聚合到一起的 trait。在 Laravel 框架中,有 40 多个类都 use InteractsWithTime;,被广泛用于缓存、队列、Console、数据库连接等组件。
源码位于 src/Illuminate/Support/InteractsWithTime.php。它只由 protected 方法组成,前提是在类内部使用。
框架内的使用示例
| 类 | 用途 |
|---|
Cache\ArrayStore / DatabaseStore 等 | TTL(有效期)的计算 |
Cache\RateLimiter | 限流的重置时间 |
Queue\Console\RestartCommand | Worker 重启时间戳 |
Database\Connection | 查询执行时间的度量 |
Console\View\Components\Task | 命令任务的耗时显示 |
Redis\Limiters\DurationLimiterBuilder | Redis 限流的时段计算 |
方法解析
secondsUntil() — 获取剩余秒数
返回距指定日期时间或延迟值的剩余秒数。参数可以是 DateTimeInterface、DateInterval,或秒数的整数。
use Illuminate\Support\InteractsWithTime;
class MyService
{
use InteractsWithTime;
public function scheduleAt(\DateTime $target): int
{
return $this->secondsUntil($target); // 从当前到 $target 的秒数
}
}
传入过去的时间会返回 0(不会为负值)。
$seconds = $this->secondsUntil(now()->addMinutes(5)); // 300
$seconds = $this->secondsUntil(now()->subMinutes(5)); // 0(过去为 0)
$seconds = $this->secondsUntil(60); // 60(整数直接作为秒数)
availableAt() — 可用时刻的 UNIX 时间戳
返回当前时间加上延迟后的 UNIX 时间戳。可用于队列任务延迟或缓存有效期计算。
$timestamp = $this->availableAt(60); // 60 秒后的 UNIX 时间戳
$timestamp = $this->availableAt(new \DateTime('2026-12-31')); // 指定日期时间的 UNIX 时间戳
$timestamp = $this->availableAt(new \DateInterval('PT5M')); // 5 分钟后
无参数调用(默认 0)时返回当前时间的时间戳。
parseDateInterval() — DateInterval 转 DateTime
若参数是 DateInterval 实例,则会加到当前时间并转换为 Carbon 实例返回。DateTimeInterface 或整数会原样返回。
$delay = $this->parseDateInterval(new \DateInterval('P1D')); // 明天的 Carbon
$delay = $this->parseDateInterval(now()->addHour()); // DateTimeInterface 原样返回
$delay = $this->parseDateInterval(3600); // 3600(整数原样返回)
secondsUntil() 与 availableAt() 内部都会调用该方法。
currentTime() — 当前时间的 UNIX 时间戳
返回 Carbon::now()->getTimestamp() 的简单包装。作为 secondsUntil() 的基准时间。
$now = $this->currentTime(); // int(UNIX 时间戳)
runTimeForHumans() — 将耗时转换为易读形式
将 microtime(true) 记录的开始时间与结束时间之差转换为易读字符串。
$start = microtime(true);
// ... 处理 ...
echo $this->runTimeForHumans($start); // 例如:"42.15ms" 或 "1s 234ms"
不足 1000ms 时以 42.15ms 的方式返回带小数的毫秒,1000ms 及以上时返回 CarbonInterval 的 forHumans() 简写形式(如 1s 234ms)。
第 2 个参数可传入结束时间,用于转换已经度量过的时间段。
$elapsed = $this->runTimeForHumans($start, $end);
在包开发中的应用
统一缓存驱动的 TTL
在编写 put(key, value, ttl) 之类同时接受 int、DateInterval、DateTime 三种 TTL 的方法时特别方便。
use Illuminate\Support\InteractsWithTime;
class MyStore
{
use InteractsWithTime;
public function put(string $key, mixed $value, mixed $ttl): void
{
$seconds = $this->secondsUntil($ttl);
// 以 $seconds(int)真正写入底层存储
$this->storage[$key] = [
'value' => $value,
'expires_at' => $this->availableAt($ttl),
];
}
}
控制台命令的耗时显示
可用于在 Artisan 命令的 handle() 中向用户展示处理耗时。
use Illuminate\Console\Command;
use Illuminate\Support\InteractsWithTime;
class ProcessDataCommand extends Command
{
use InteractsWithTime;
public function handle(): void
{
$start = microtime(true);
// ... 处理 ...
$this->info("完成:{$this->runTimeForHumans($start)}");
}
}
测试用的 InteractsWithTime
Illuminate\Foundation\Testing\Concerns\InteractsWithTime 是另一个 trait,提供在测试用例中操作时间的 travel*() 方法(会自动集成到 TestCase)。
// 在测试中前进时间(Testing\Concerns\InteractsWithTime)
$this->travel(5)->days();
$this->travelTo(now()->addMonth());
$this->travelBack();
它与本页所讲的 Illuminate\Support\InteractsWithTime 命名空间不同,注意不要混淆。
| 方法 | 返回值 | 主要用途 |
|---|
secondsUntil($delay) | int | 获取剩余秒数 |
availableAt($delay) | int | 计算生效时间戳 |
parseDateInterval($delay) | DateTimeInterface|int | DateInterval → Carbon 转换 |
currentTime() | int | 当前 UNIX 时间戳 |
runTimeForHumans($start, $end) | string | 面向人类的耗时展示 |
想编写既能接受 int、又能接受 DateInterval、DateTimeInterface 的方法时,只需 use 这个 trait,即可复用其转换逻辑。
相关页面