Weave Code
Code Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Clock Laravel Package

eventsauce/clock

Simple clock abstraction for PHP. Use SystemClock in production and TestClock in tests to control time deterministically. Get now() as DateTimeImmutable, access timeZone(), move time forward, tick to system time, or fixate to a specific moment.

View on GitHub
Deep Wiki
Context7

Getting Started

Minimal Setup

  1. Installation

    composer require eventsauce/clock
    

    Add to composer.json if using a custom package:

    "require": {
        "eventsauce/clock": "^2.0"
    }
    
  2. Basic Usage The package provides a Clock interface and a default SystemClock implementation. Start by injecting the Clock interface into your services:

    use EventSauce\Clock\Clock;
    
    class MyService {
        public function __construct(private Clock $clock) {}
    }
    
  3. First Use Case: Time-Aware Logic Use the clock()->now() method to get the current time in a deterministic way:

    $now = $clock->now(); // Returns a \DateTimeImmutable
    

Implementation Patterns

Dependency Injection

  • Laravel Service Provider Bind the Clock interface to a concrete implementation (e.g., SystemClock or a custom clock) in a service provider:

    use EventSauce\Clock\Clock;
    use EventSauce\Clock\SystemClock;
    
    public function register() {
        $this->app->bind(Clock::class, function () {
            return new SystemClock();
        });
    }
    
  • Testing with Fake Clocks Replace SystemClock with a FakeClock for predictable tests:

    use EventSauce\Clock\FakeClock;
    
    $clock = new FakeClock(new \DateTimeImmutable('2023-01-01'));
    $this->app->instance(Clock::class, $clock);
    

Time-Based Workflows

  • Scheduling Use the clock to determine if a task should run:

    if ($clock->now() > $scheduledTime) {
        $this->executeTask();
    }
    
  • Time Windows Validate time-based constraints (e.g., business hours):

    $openTime = new \DateTimeImmutable('09:00');
    $closeTime = new \DateTimeImmutable('17:00');
    $now = $clock->now();
    
    if ($now < $openTime || $now > $closeTime) {
        throw new \RuntimeException('Outside business hours');
    }
    
  • Time Travel for Debugging In tests, simulate time progression:

    $clock->setTime(new \DateTimeImmutable('2023-01-02'));
    

Integration with Laravel Features

  • Queues and Jobs Use the clock to determine job execution time:

    class ProcessOrder implements ShouldQueue {
        public function __construct(private Clock $clock) {}
    
        public function handle() {
            $this->logExecutionTime($this->clock->now());
        }
    }
    
  • Caching Use the clock for cache invalidation logic:

    $cacheKey = 'user:'.$userId;
    $lastUpdated = $this->cache->get($cacheKey . ':last_updated');
    
    if ($lastUpdated && $this->clock->now() > $lastUpdated->modify('+1 hour')) {
        $this->cache->forget($cacheKey);
    }
    

Gotchas and Tips

Pitfalls

  • Time Zone Sensitivity The SystemClock uses the system's default time zone. Ensure consistency across environments:

    // Force a time zone (e.g., in a service provider)
    date_default_timezone_set('UTC');
    
  • Immutable DateTime The clock returns DateTimeImmutable objects. Avoid modifying them directly:

    // Bad: Modifies the original
    $now = $clock->now();
    $now->modify('+1 day');
    
    // Good: Creates a new instance
    $tomorrow = $clock->now()->modify('+1 day');
    
  • Thread Safety The SystemClock is thread-safe, but custom clocks may not be. Ensure thread safety if extending:

    class CustomClock implements Clock {
        private $time;
    
        public function __construct(\DateTimeImmutable $initialTime) {
            $this->time = $initialTime;
        }
    
        public function now(): \DateTimeImmutable {
            return $this->time; // Thread-safe if $this->time is immutable
        }
    }
    

Debugging

  • Log Clock Time Add logging to track time progression in tests or production:

    \Log::debug('Current clock time:', ['time' => $clock->now()->format('Y-m-d H:i:s')]);
    
  • Verify FakeClock in Tests Ensure FakeClock is properly injected and used:

    $this->app->instance(Clock::class, new FakeClock(new \DateTimeImmutable('2023-01-01')));
    $this->assertEquals('2023-01-01', $clock->now()->format('Y-m-d'));
    

Extension Points

  • Custom Clock Implementations Create a clock for specific use cases (e.g., database-backed time):

    class DatabaseClock implements Clock {
        public function now(): \DateTimeImmutable {
            return \DB::table('clock')->value('current_time');
        }
    }
    
  • Time Adjustment Middleware Wrap the clock to adjust time for testing or feature flags:

    class AdjustedClock implements Clock {
        public function __construct(private Clock $clock, private int $offsetMinutes = 0) {}
    
        public function now(): \DateTimeImmutable {
            return $this->clock->now()->modify("+{$this->offsetMinutes} minutes");
        }
    }
    
  • Clock-Aware Models Extend Eloquent models to use the clock for time-sensitive logic:

    use EventSauce\Clock\Clock;
    
    class Post extends Model {
        public function __construct(array $attributes = [], Clock $clock) {
            parent::__construct($attributes);
            $this->clock = $clock;
        }
    
        public function isRecent(): bool {
            return $this->clock->now() < $this->created_at->modify('+7 days');
        }
    }
    
Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
davejamesmiller/laravel-breadcrumbs
artisanry/parsedown
christhompsontldr/phpsdk
enqueue/dsn
bunny/bunny
enqueue/test
enqueue/null
enqueue/amqp-tools
milesj/emojibase
bower-asset/punycode
bower-asset/inputmask
bower-asset/jquery
bower-asset/yii2-pjax
laravel/nova
spatie/laravel-mailcoach
spatie/laravel-superseeder
laravel/liferaft
nst/json-test-suite
danielmiessler/sec-lists
jackalope/jackalope-transport