psr/clock
PSR-20 Clock interface for PHP. Defines ClockInterface::now() returning DateTimeImmutable, enabling dependency injection of time sources and easy testing. This package provides only the interface; use or create an implementation.
Start by installing the package:
composer require psr/clock
This package only defines the Psr\Clock\ClockInterface—it does not provide an implementation. To get started, install an implementation such as php-http/clock or symfony/clock:
composer require symfony/clock
Your first use case is dependency injection of time. Instead of calling new DateTimeImmutable() or time() directly in business logic, inject ClockInterface into services that need the current time. This makes your code testable and decoupled from real-world time.
Example minimal integration:
use Symfony\Component\Clock\Clock;
use Psr\Clock\ClockInterface;
$clock = new Clock(); // implements ClockInterface
$service = new MyService($clock);
Constructor injection: Inject ClockInterface into any class that needs to know "now", especially for time-based logic (e.g., expiry checks, rate limits, scheduling).
Testing with mock clocks: In tests, inject a deterministic ClockInterface implementation (e.g., php-mock/php-mock-clock or your own stub). Example:
$mockClock = new class implements ClockInterface {
public function now(): DateTimeImmutable {
return new DateTimeImmutable('2023-01-01 00:00:00');
}
};
Framework integration: In Laravel, bind ClockInterface to Symfony\Component\Clock\Clock in a service provider:
$this->app->singleton(ClockInterface::class, fn () => new Symfony\Component\Clock\Clock);
Package development: If your package needs time, depend on psr/clock, and do not require a specific implementation. Let downstream applications provide their own clock.
provide metadata: When releasing a package that implements the interface, declare it in composer.json:
"provide": {
"psr/clock-implementation": "1.0.0"
}
⚠️ No built-in clock: psr/clock is only an interface. Forgetting to require an implementation is the most common pitfall—expect UnresolvableDependency errors at runtime.
⚠️ Mutable vs. Immutable time: The interface returns DateTimeImmutable. Never return a mutable DateTime—violating this breaks expectations and can cause hard-to-debug concurrency/time-travel issues.
🔁 Testing edge cases: Use mock clocks to simulate time jumps (e.g., DST transitions), aging tokens, or expiring sessions without waiting.
🧪 Testing with phpunit: Consider tools like php-mock/php-mock-clock that integrate with PHPUnit’s assertThat() assertions.
🧠 Why not Carbon or Nora? psr/clock is intentionally minimal. It’s not for time manipulation—use DateTimeImmutable + DateInterval + helpers like symfony/process or nesbot/carbon only when actual time arithmetic is needed. Reserve ClockInterface strictly for acquiring the current moment.
🚀 Future-proofing: Any new library adopting PSR-20 will work seamlessly with your ClockInterface-typed code. Use it consistently in public APIs.
How can I help you explore Laravel packages today?