lcobucci/clock
Clock abstraction for PHP to decouple your code from DateTimeImmutable instantiation. Depend on the Clock interface and use SystemClock for real time (with timezone support) or FrozenClock for deterministic, test-friendly time in unit tests.
Clock interface is explicitly designed for DI, fitting Laravel’s service container and dependency injection patterns. This enables mocking time in tests without side effects.SystemClock::fromUTC(), SystemClock::fromSystemTimezone()) aligns with Laravel’s global timezone configuration (config/app.php), reducing ambiguity in distributed systems.SystemClock is marked as @immutable and readonly, preventing accidental state modification—a critical feature for thread-safe and predictable Laravel applications (e.g., queue workers, background jobs).Clock interface to a default implementation (e.g., SystemClock) in Laravel’s service container.Clock::now()) to abstract the interface, mirroring Laravel’s Cache, Auth, and Log facades.TimeAdjusted, ClockFrozen) when switching between SystemClock and FrozenClock.| Risk Area | Mitigation Strategy |
|---|---|
| PHP Version Mismatch | Laravel 10+ requires PHP 8.2+. The package supports PHP 8.4+ (latest stable). Upgrade path: Test with Laravel’s PHP version matrix. |
| Breaking Changes | PSR-20 adoption (v3.0.0) is backward-compatible with Laravel’s existing Carbon/DateTime usage. Risk: Minimal if using the interface. |
| Performance Overhead | SystemClock uses DateTimeImmutable::now(), which is optimized in PHP. Benchmark against now() in Laravel’s Carbon facade. |
| Testing Complexity | FrozenClock simplifies time manipulation in tests. Risk: Developers may forget to reset clocks post-test. Solution: Use Laravel’s test helpers or a ClockManager facade. |
SystemClock?
DateTimeImmutable, which accounts for timezone rules. No additional logic needed.FrozenClock be used in production?
SystemClock in production.Carbon facade?
DateTimeImmutable objects, which Carbon can instantiate from. No direct conflict.now() to Clock::now()?
now() to Clock::now() temporarily during transition.Clock interface to implement a custom provider (e.g., DatabaseClock).Clock interface to SystemClock in AppServiceProvider.Clock facade for fluent access (e.g., Clock::now()).FrozenClock in PHPUnit tests via createMock(Clock::class) or Laravel’s partialMock.DateTimeImmutable is interchangeable with Carbon\Carbon.now() with Clock::now() in job classes for deterministic testing.scheduler and events systems for time-based triggers.| Phase | Action | Tools/Techniques |
|---|---|---|
| Assessment | Audit all now()/Carbon::now() usages in codebase. |
grep, IDE refactoring tools. |
| Interface Adoption | Replace direct DateTimeImmutable instantiation with Clock interface. |
Laravel IDE Helper, Rector. |
| Facade Rollout | Introduce Clock facade and alias now() to Clock::now(). |
Laravel’s aliases.php. |
| Testing | Replace DateTime::createFromFormat() in tests with FrozenClock. |
Laravel’s refreshDatabase() + FrozenClock. |
| Production | Deploy with SystemClock as default; monitor for timezone edge cases. |
Sentry, Laravel Logs. |
spatie/laravel-activitylog).Clock-aware adapter.now() usage).now() in job classes to enable replayable tests.created_at) to use Clock.now()->format() with Clock::now()->format() in templates.update or Laravel Forge for updates.Clock usage in Laravel’s app.php to trace time-related issues:
Clock::shouldLogUsage(true); // Hypothetical feature; use middleware otherwise.
SystemClock::fromUTC() in CI/CD to avoid DST surprises.ClockReset trait to Laravel’s test case base class.SystemClock is stateless and thread-safe. No scaling concerns in Laravel’s request/queue model.Clock::now() vs. now() in a load-tested Laravel app (e.g., 10K RPS).SystemClock with UTC to avoid timezone inconsistencies across microservices.Clock implementation that syncs with a distributed time source (e.g., Chronos).| Failure Scenario | Impact | Mitigation |
|---|---|---|
| Clock Not Bound in Container | Clock resolution fails. |
Use Laravel’s bindIf() in AppServiceProvider. |
| FrozenClock in Production | Time stands still. | Runtime check: Throw RuntimeException if FrozenClock is detected. |
| Timezone Mismatch | Inconsistent timestamps. | Enforce UTC in SystemClock for APIs. |
| **Clock |
How can I help you explore Laravel packages today?