Weave 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

rikudou/clock

A lightweight clock abstraction for PHP that makes time-dependent code easier to test. Inject a clock instead of calling time() directly, use the system clock in production, and swap in a fixed or mocked clock in tests to control dates and durations reliably. Framework-agnostic and simple to integra...

View on GitHub
Deep Wiki
Context7

Getting Started

Install via Composer:

composer require rikudou/clock

Start by opening src/ — the package is intentionally tiny, essentially one or two classes around a now() method. Check composer.json for psr/clock in require (which would mean it implements Psr\Clock\ClockInterface) and confirm the exact namespace (Rikudou\Clock\...). That interface is what you'll type-hint throughout your application.

The first use case is almost always the same: a service that calls new DateTimeImmutable() or time() inline, making it untestable. Swap that call for an injected clock:

use Rikudou\Clock\ClockInterface; // confirm exact FQCN in src/

final class SubscriptionRenewer
{
    public function __construct(private ClockInterface $clock) {}

    public function renew(Subscription $subscription): void
    {
        $subscription->setExpiresAt(
            $this->clock->now()->modify('+1 month')
        );
    }
}

Register the system clock in your container (Laravel: a singleton() binding in AppServiceProvider::register()), and from that point you have one seam for all time-dependent behavior.

Implementation Patterns

Constructor injection, interface-first. Never type-hint a concrete clock in domain code. Bind the interface to a system clock singleton in production, and to a frozen clock in tests. This is the entire payoff of the package.

Frozen clock for tests. If the package doesn't ship one, a five-line anonymous class is enough:

$clock = new class(new DateTimeImmutable('2024-01-01 00:00:00')) implements ClockInterface {
    public function __construct(private DateTimeImmutable $now) {}
    public function now(): DateTimeImmutable { return $this->now; }
};
$this->app->instance(ClockInterface::class, $clock);

Use it wherever domain time matters. Token TTLs, subscription expirations, "created at" stamps, age gates, scheduled promotions, rate-limit windows. Leave infra-level timestamps (Laravel's created_at magic) alone — those are fine.

Wrap repetitive arithmetic in a domain helper. If you keep writing ->modify('+30 days'), a TokenClock decorator around the package clock keeps call sites readable.

Workflow tip: audit for now(), time(), new DateTime, date(), Carbon::now(). Each hit is a candidate. Migrate one service at a time, running tests after each.

Laravel integration — bind once:

// AppServiceProvider::register()
$this->app->singleton(ClockInterface::class, fn () => new SystemClock());

Then any resolved class gets it automatically. No facade needed.

Gotchas and Tips

Verify the exact API first. This is a tiny package — one developer, one star — so don't assume the namespace or that it implements PSR-20. If it does, you can freely swap it for laminas/laminas-clock, symfony/clock, or a PSR-20 adapter. If not, wrap it in your own thin interface so you're not locked in.

Timezone is the classic trap. Decide up front whether now() returns UTC or local-system time. If it uses new DateTimeImmutable() internally, it picks up PHP's date.timezone, so production and CI can disagree. Set date_default_timezone_set('UTC') at bootstrap and convert to display timezones only at the edges.

Immutability matters. If now() returns DateTimeImmutable, modify() returns a new instance and shared state stays clean. If it ever returns a mutable DateTime, clone before modifying — otherwise anything holding the clock gets corrupted.

Don't over-inject. Only classes whose behavior depends on when they run need the clock. A repository that just persists entities doesn't. Spreading it everywhere makes constructors noisy.

Long-running workers. A clock returns the current time at each call, so queue workers are fine — but if you cache a now() value in a constructor, you freeze it at boot. Always call $this->clock->now() at the moment you need it.

Debugging time bugs: when something behaves differently in tests vs. prod, first check which clock is bound. A stray new DateTimeImmutable() in the same class is the usual culprit.

Extension points. Write OffsetClock (delegates, adds a duration), LoggingClock (records calls), or SteppingClock (advances on each now() call) — each trivial, and useful for replaying slow-day scenarios or asserting call order.

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.
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route