> ## Documentation Index
> Fetch the complete documentation index at: https://kawax.biz/llms.txt
> Use this file to discover all available pages before exploring further.

# InteractsWithTime trait

> 讲解队列、缓存、调度中都会用到的时间计算工具 trait，及其在实际项目中的用法

## 什么是 InteractsWithTime

`Illuminate\Support\InteractsWithTime` 是把时间、延迟、耗时计算聚合到一起的 trait。在 Laravel 框架中，有 40 多个类都 `use InteractsWithTime;`，被广泛用于缓存、队列、Console、数据库连接等组件。

<Info>
  源码位于 `src/Illuminate/Support/InteractsWithTime.php`。它只由 `protected` 方法组成，前提是在类内部使用。
</Info>

## 框架内的使用示例

| 类                                       | 用途            |
| --------------------------------------- | ------------- |
| `Cache\ArrayStore` / `DatabaseStore` 等  | TTL（有效期）的计算   |
| `Cache\RateLimiter`                     | 限流的重置时间       |
| `Queue\Console\RestartCommand`          | Worker 重启时间戳  |
| `Database\Connection`                   | 查询执行时间的度量     |
| `Console\View\Components\Task`          | 命令任务的耗时显示     |
| `Redis\Limiters\DurationLimiterBuilder` | Redis 限流的时段计算 |

## 方法解析

### `secondsUntil()` — 获取剩余秒数

返回距指定日期时间或延迟值的剩余秒数。参数可以是 `DateTimeInterface`、`DateInterval`，或秒数的整数。

```php theme={null}
use Illuminate\Support\InteractsWithTime;

class MyService
{
    use InteractsWithTime;

    public function scheduleAt(\DateTime $target): int
    {
        return $this->secondsUntil($target); // 从当前到 $target 的秒数
    }
}
```

传入过去的时间会返回 `0`（不会为负值）。

```php theme={null}
$seconds = $this->secondsUntil(now()->addMinutes(5)); // 300
$seconds = $this->secondsUntil(now()->subMinutes(5)); // 0（过去为 0）
$seconds = $this->secondsUntil(60);                   // 60（整数直接作为秒数）
```

### `availableAt()` — 可用时刻的 UNIX 时间戳

返回当前时间加上延迟后的 UNIX 时间戳。可用于队列任务延迟或缓存有效期计算。

```php theme={null}
$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` 或整数会原样返回。

```php theme={null}
$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()` 的基准时间。

```php theme={null}
$now = $this->currentTime(); // int（UNIX 时间戳）
```

### `runTimeForHumans()` — 将耗时转换为易读形式

将 `microtime(true)` 记录的开始时间与结束时间之差转换为易读字符串。

```php theme={null}
$start = microtime(true);

// ... 处理 ...

echo $this->runTimeForHumans($start); // 例如："42.15ms" 或 "1s 234ms"
```

不足 1000ms 时以 `42.15ms` 的方式返回带小数的毫秒，1000ms 及以上时返回 CarbonInterval 的 `forHumans()` 简写形式（如 `1s 234ms`）。

第 2 个参数可传入结束时间，用于转换已经度量过的时间段。

```php theme={null}
$elapsed = $this->runTimeForHumans($start, $end);
```

## 在包开发中的应用

### 统一缓存驱动的 TTL

在编写 `put(key, value, ttl)` 之类同时接受 `int`、`DateInterval`、`DateTime` 三种 TTL 的方法时特别方便。

```php theme={null}
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()` 中向用户展示处理耗时。

```php theme={null}
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`）。

```php theme={null}
// 在测试中前进时间（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，即可复用其转换逻辑。

## 相关页面

* [包开发](/zh/advanced/package-development)
* [InteractsWithData trait](/zh/advanced/interacts-with-data)
* [Conditionable trait](/zh/advanced/conditionable)


## Related topics

- [InteractsWithData trait](/zh/advanced/interacts-with-data.md)
- [广播](/zh/broadcasting.md)
- [PHP 属性](/zh/advanced/php-attributes.md)
- [Fluent 类](/zh/advanced/fluent.md)
- [Conditionable trait](/zh/advanced/conditionable.md)
