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

Datetime Provider Laravel Package

kdyby/datetime-provider

Kdyby/DatetimeProvider is a Nette Framework extension that registers a DateTime provider service for obtaining the current date and time. Inject it instead of creating DateTime instances directly, making time-dependent code testable, mockable, and configurable via NEON configuration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

What the package actually does. Unchanged. kdyby/datetime-provider is a small Nette-ecosystem utility built around a single idea: instead of calling new \DateTime(), date(), or time() directly, application code asks an injected provider service for the current date, time, datetime, and timezone. That indirection lets tests freeze or offset "now" deterministically, and gives one consistent notion of the current instant across a request. The value is in the pattern, not the code — the implementation is a handful of classes wrapping \DateTimeImmutable plus a test/controllable variant, registered through a Nette DI compiler extension.

What v1.0.0 actually changes. The release notes contain one sentence — "first stable version" — and a link to documentation. There is no changelog, no feature list, no breaking-change notice, no deprecation list, no PHP support statement, and no license clarification. As of this review the Packagist/GitHub metadata was not re-pulled (the data payload supplied was empty), so star count, dependents, license classification, and the composer.json constraints must be treated as unverified rather than confirmed unchanged. Net effect: the release is a maturity signal, not an information event. It tells us a maintainer is still reachable and has chosen to commit to a semver-stable API. It does not address — and the notes give no basis to assume it addresses — a single one of the material objections below.

Architecture fit — still poor for a Laravel codebase. The package remains a Nette CompilerExtension package. Laravel has no automatic path to register or resolve these services; adoption requires hand-written service-provider bindings and, in practice, replacing the Nette extension with your own wiring. At that point you are using maybe 60–100 lines of vendor code and rewriting most of the integration surface. A 1.0.0 tag does not build a bridge.

Integration feasibility — technically easy, strategically pointless. Unchanged. Installing it pulls nette/di (and likely nette/utils) into a Laravel application, importing a second, unrelated DI container and its version constraints into your dependency graph for no benefit. More importantly, the package's only real selling point is already native to the stack: Laravel ships Illuminate\Support\Carbon::setTestNow(), plus travel(), travelTo(), and freezeTime() in the test case, and Carbon's setTestNow() covers the frozen-clock case globally. There is no capability gap to close.

If the 1.0.0 release did anything useful, it is most likely a composer.json modernization (PHP constraint bump alone). That is a precondition for adoption, not a reason for it — it lowers the cost of the option we have already declined.

Technical risk — high for the size of the prize.

  • Maintenance / staleness: materially softened, not resolved. The prior assessment's claim that the last release was 2018-02-14 and that the maintainer "has already departed" is now falsified — a release happened. But a single tag after a multi-year gap is a pulse, not a track record. There is still no history of responsive issue triage or security handling to extrapolate from.
  • PHP compatibility: unverified. Whether v1.0.0 relaxes the era-appropriate php and nette/* constraints to admit 8.1–8.4 is exactly what the release note does not say. Assume nothing until the tag's composer.json is read.
  • Licensing: unchanged and still the single hardest blocker. NOASSERTION meant GitHub/Packagist could not classify the license. Nothing in the release note indicates a LICENSE change or a license field added to composer.json. Until a human reads the LICENSE file at the v1.0.0 tag and legal signs off, treat it as all-rights-reserved — no redistribution, no vendoring into a proprietary repo. A version tag cannot grant rights.
  • No adoption signal: likely unchanged. Ten stars and zero dependents meant zero battle-testing, no issue history to mine, no community to ask. Going 1.0.0 without consumers means the stability promise is untested by anyone but the author.
  • Attack surface remains low (no I/O, no network, no deserialization), so security risk is small — but so is the reward.

Key questions to resolve before any decision.

  1. What actually changed between the previous tag and v1.0.0? Read the diff and the tagged composer.json, not the release note. Specifically: PHP constraint, nette/* constraints, namespace/API breaks, and whether the license field was set.
  2. What exactly does the LICENSE file at v1.0.0 say, and does legal permit vendoring a copy?
  3. Does the code run on PHP 8.1–8.4 without forking, now that a stable constraint set may exist?
  4. Does it expose a mutable/frozen mode suitable for tests, or only a wall-clock implementation?
  5. Is the "consistent timezone across the request" behavior configurable, or hard-coded to the Nette config layer?
  6. Has anything been published indicating issue triage intent — roadmap, response commitments, CI matrix — or is v1.0.0 a one-off tag?

Recommendation: still do not adopt. The release is a genuine but non-decisive data point: it removes "abandoned" from the objection list and leaves "unattested." The license ambiguity, the foreign DI container, and the redundancy with native Laravel/Carbon and PSR-20 are all untouched. Reimplement the interface, or adopt PSR-20 (Psr\Clock\ClockInterface + symfony/clock) and bind it in AppServiceProvider. Re-open this assessment only if all three of the following land: a resolvable OSI license at v1.0.0, verified PHP 8.1+ support without forking, and evidence of at least one external production dependent. Until then this is a reimplementation-with-inspiration exercise, and a 1.0.0 tag on code you were going to rewrite is worth roughly nothing.

Integration Approach

Stack fit. Still effectively none out of the box: Nette package, Laravel target, no bridge. Treat any adoption as a reimplementation with inspiration, not an integration. The 1.0.0 documentation link is worth skimming for the semantic contract (what "current date" vs "current datetime" vs "current timezone" mean, and how the controllable variant is intended to be driven), then discard the code path.

Migration path (recommended).

  1. Define a narrow port in the app, ideally Psr\Clock\ClockInterface (now(): DateTimeImmutable) plus your own TimeProvider interface if you need getCurrentDate() / getCurrentTime() / getCurrentTimezone() parity with the Kdyby shape.
  2. Provide two adapters: SystemClock (production, wraps Symfony\Component\Clock\Clock) and FrozenClock (tests, explicit instant, immutable).
  3. Bind in AppServiceProvider: SystemClock in production, FrozenClock swapped in the base TestCase or via a dedicated trait.
  4. Mechanically replace direct "now" call sites — now(), Carbon::now(), date(), time(), new \DateTime() — with the injected clock. This is the real work and it is identical whether or not you install the package.
  5. Add a guard: a PHPStan custom rule or an architecture test (e.g. Pest/PHPUnit assertion over token_get_all, or spatie/php-structure-discoverer) that fails CI on new direct now() calls in domain code. Without this, the abstraction decays in weeks.

Compatibility. Unchanged pending verification. If someone insists on the actual package, expect one of two outcomes at v1.0.0: either the constraints were modernized and it resolves alongside current Laravel (best case — you still carry nette/di), or they were not and you fork-and-repatriate them. Either way, budget a manual audit of \DateTime behavior on PHP 8. Budget 1–3 days including legal review, versus roughly half a day to write the equivalent from scratch.

Sequencing. (a) Legal/license read at the v1.0.0 tag — do this first, it can terminate the option cheaply. (b) Diff v1.0.0 against the prior tag and read the tagged composer.json — 30 minutes, and it retires most of the open questions. (c) Two-hour source/doc read to confirm the API surface and test-clock semantics. (d) Spike: hand-rolled clock + one module migrated + tests green. (e) Call-site sweep by module, one PR per bounded context. (f) CI guard rule. (g) Retire any interim shim. Steps (a)–(d) fit inside a single sprint-week; the sweep is the only multi-sprint item and is entirely agnostic to the package choice.

Operational Impact

Maintenance. Full ownership still transfers to you on day one, and that has not changed — but the "nothing upstream since 2018" framing must be retired. The accurate statement is: one release after a multi-year gap, single maintainer, no observable triage history. If you vendor it, every future PHP upgrade is your problem; the code is small enough that this is manageable, but it is strictly worse than owning a 40-line interface you wrote and understand.

Support. No vendor, no SLA, no community forum. The v1.0.0 documentation improves the reading experience and is a real, if minor, onboarding asset; it does not create an escalation path. Internal engineers remain the only route, and a maintainer who surfaces once every several years is not a support channel. The ramp-up cost — an hour for any PHP developer — stays low and is not where the risk lives.

Scaling. Not a concern in either direction and unchanged by the release. The provider is a stateless wrapper around DateTimeImmutable; per-call cost is negligible and it introduces no shared state, no locks, no allocation pressure. The scaling-adjacent consideration is correctness under long-lived processes rather than throughput.

Failure modes to design against.

  • Frozen clock leaking to production — a test-mode flag or misconfigured binding that pins now() will silently corrupt timestamps, expiry logic, and audit trails. Fail loudly: assert clock class at boot.
  • Long-lived workers — under Octane, queue workers, or Swoole, a clock bound once per container can outlive the request. Bind as scoped/transient, never singleton-with-mutable-state, and re-resolve per job.
  • Serialization — providers injected into queued jobs do not survive serialization; re-resolve from the container in handle().
  • Timezone drift at boundaries — "consistent timezone across the request" is the package's stated benefit and is also its sharpest edge: DST transitions, UTC-vs-local persistence, and date-only comparisons are where bugs land. Pin storage to UTC and convert at the edges.
  • Wall clock vs monotonic clock — this abstraction is wall time only. Duration measurement, retries, and timeouts must use hrtime(); conflating the two produces negative elapsed times under NTP correction.
  • Abstraction decay — without the CI guard, developers revert to now() and the invariant dies quietly.
  • New in this review: semver-tag complacency. A 1.0.0 badge reads to reviewers as "stable and supported" and can suppress the diligence this package still requires. If it appears in a dependency proposal, attach the license and PHP-constraint findings to that ticket so the tag does not do the persuading.

Ramp-up. Under a day for a mid-level PHP developer to learn the pattern and the two adapters; the new documentation may shave that further. The cost is not comprehension; it is the mechanical sweep of existing call sites and the discipline to keep them swept. That cost is identical for the package and for a homegrown equivalent — which remains the core argument for not taking on an ambiguously licensed Nette dependency to obtain a pattern the framework already ships.

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/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
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