PHPackages                             phpnomad/chrono - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Utility &amp; Helpers](/categories/utility)
4. /
5. phpnomad/chrono

ActiveLibrary[Utility &amp; Helpers](/categories/utility)

phpnomad/chrono
===============

Time-related contract interfaces for PHPNomad. Ships interfaces only — pair with a concrete integration package (e.g. wordpress-integration).

1.0.1(1mo ago)09273MITPHPPHP &gt;=8.2

Since May 27Pushed 1mo agoCompare

[ Source](https://github.com/phpnomad/chrono)[ Packagist](https://packagist.org/packages/phpnomad/chrono)[ Docs](https://github.com/phpnomad/chrono)[ RSS](/packages/phpnomad-chrono/feed)WikiDiscussions main Synced 1w ago

READMEChangelog (2)Dependencies (4)Versions (3)Used By (3)

PHPNomad Chrono
===============

[](#phpnomad-chrono)

Time-related strategy interfaces for PHPNomad. A catalog of narrow capabilities that integration packages implement against any underlying time library — PSR-20, Carbon, Tokei, lcobucci/clock, symfony/clock, WordPress core, native PHP — so consumers can compose time-handling capabilities across libraries without touching call sites.

This package ships **interfaces only**. Pair it with one or more integration packages — for example [`phpnomad/wordpress-integration`](https://github.com/phpnomad/wordpress-integration), which binds WordPress's `current_datetime()`, `wp_timezone()`, `wp_date()`, and `human_time_diff()` to the appropriate interfaces.

Requirements
------------

[](#requirements)

PHP 8.2 or newer.

Installation
------------

[](#installation)

```
composer require phpnomad/chrono
```

You will also need at least one concrete `ClockStrategy` binding. On WordPress, install [`phpnomad/wordpress-integration`](https://github.com/phpnomad/wordpress-integration) and the wiring is automatic. Elsewhere, bind any [PSR-20](https://www.php-fig.org/psr/psr-20/) `ClockInterface` implementation (e.g. [`lcobucci/clock`](https://github.com/lcobucci/clock) or [`symfony/clock`](https://github.com/symfony/clock)) to `ClockStrategy` in your composition root.

Usage
-----

[](#usage)

Inject the capabilities you need. A consumer that does not care about formatting or arithmetic depends on `ClockStrategy` alone:

```
use DateTimeImmutable;
use PHPNomad\Chrono\Interfaces\CanCheckIfPast;
use PHPNomad\Chrono\Interfaces\ClockStrategy;

final class TokenService
{
    public function __construct(
        private ClockStrategy $clock,
        private CanCheckIfPast $past,
    ) {}

    public function isExpired(DateTimeImmutable $expiresAt): bool
    {
        return $this->past->isPast($expiresAt);
    }

    public function issueExpiringIn(string $relative): DateTimeImmutable
    {
        return $this->clock->now()->modify($relative);
    }
}
```

In tests, bind a frozen `ClockStrategy` and a stub `CanCheckIfPast`:

```
$clock = new Lcobucci\Clock\FrozenClock(new DateTimeImmutable('2026-05-27T12:00:00Z'));
$past  = new class ($clock) implements CanCheckIfPast {
    public function __construct(private ClockStrategy $clock) {}
    public function isPast(DateTimeImmutable $i): bool { return $i < $this->clock->now(); }
};
$service = new TokenService($clock, $past);

$this->assertFalse($service->isExpired(new DateTimeImmutable('2026-05-27T13:00:00Z')));
$this->assertTrue($service->isExpired(new DateTimeImmutable('2026-05-27T11:00:00Z')));
```

Catalog
-------

[](#catalog)

Each interface is narrow — one or a few related methods — so integrators can implement whatever subset their underlying library naturally covers. A single concrete class can implement many interfaces.

### Clock and provider state

[](#clock-and-provider-state)

InterfaceMethodNotes`ClockStrategy``now(): DateTimeImmutable`Extends `Psr\Clock\ClockInterface``HasTimezone``getTimezone(): DateTimeZone`Platform's configured timezone`HasLocale``getLocale(): string`Platform's configured locale (BCP 47 / POSIX style)### Predicates on a single instant

[](#predicates-on-a-single-instant)

InterfaceMethod`CanCheckIfPast``isPast(DateTimeImmutable $instant): bool``CanCheckIfFuture``isFuture(DateTimeImmutable $instant): bool``CanCheckIfWeekend``isWeekend(DateTimeImmutable $instant): bool``CanCheckIfWeekday``isWeekday(DateTimeImmutable $instant): bool`### Predicates on two instants

[](#predicates-on-two-instants)

InterfaceMethod`CanCheckSameDay``isSameDay(DateTimeImmutable $a, DateTimeImmutable $b): bool``CanCheckSameMonth``isSameMonth(DateTimeImmutable $a, DateTimeImmutable $b): bool``CanCheckSameYear``isSameYear(DateTimeImmutable $a, DateTimeImmutable $b): bool``CanCheckBetween``isBetween(DateTimeImmutable $i, DateTimeImmutable $start, DateTimeImmutable $end): bool`### Arithmetic

[](#arithmetic)

InterfaceMethod`CanApplyModifier``apply(DateTimeImmutable $instant, string $modifier): DateTimeImmutable``CanAddInterval``add(DateTimeImmutable $instant, DateInterval $interval): DateTimeImmutable``CanSubtractInterval``subtract(DateTimeImmutable $instant, DateInterval $interval): DateTimeImmutable`### Calendar boundaries

[](#calendar-boundaries)

InterfaceMethod`CanGetStartOfDay``startOfDay(DateTimeImmutable $instant): DateTimeImmutable``CanGetEndOfDay``endOfDay(DateTimeImmutable $instant): DateTimeImmutable``CanGetStartOfMonth``startOfMonth(DateTimeImmutable $instant): DateTimeImmutable``CanGetEndOfMonth``endOfMonth(DateTimeImmutable $instant): DateTimeImmutable``CanGetStartOfYear``startOfYear(DateTimeImmutable $instant): DateTimeImmutable``CanGetEndOfYear``endOfYear(DateTimeImmutable $instant): DateTimeImmutable`### Difference and duration

[](#difference-and-duration)

InterfaceMethod`CanGetDifference``diff(DateTimeImmutable $a, DateTimeImmutable $b): DateInterval``CanGetDifferenceInDays``diffInDays(DateTimeImmutable $a, DateTimeImmutable $b): int``CanGetDifferenceInHours``diffInHours(DateTimeImmutable $a, DateTimeImmutable $b): int``CanGetDifferenceInMinutes``diffInMinutes(DateTimeImmutable $a, DateTimeImmutable $b): int``CanGetDifferenceInSeconds``diffInSeconds(DateTimeImmutable $a, DateTimeImmutable $b): int`### Parsing

[](#parsing)

InterfaceMethod`CanParseDate``parse(string $expression): DateTimeImmutable``CanParseDateWithFormat``parseFormat(string $expression, string $format): DateTimeImmutable`### Formatting

[](#formatting)

InterfaceMethod`CanFormatDate``format(DateTimeImmutable $instant, string $format): string``CanFormatLocalizedDate``formatLocalized(DateTimeImmutable $instant, string $format): string``CanFormatRelativeTime``relative(DateTimeImmutable $instant): string` ("3 hours ago")### Model contracts

[](#model-contracts)

These two are model-side contracts for persisted records — every PHPNomad model that participates in audit trails implements them.

InterfaceMethod`HasCreatedDate``getCreatedDate(): DateTimeImmutable``HasModifiedDate``getModifiedDate(): DateTimeImmutable`How integrations compose the catalog
------------------------------------

[](#how-integrations-compose-the-catalog)

An integration package ships one or more concrete classes that implement the cluster of interfaces its underlying library can naturally fulfill. `phpnomad/wordpress-integration` ships a class implementing the WordPress-specific subset:

```
class WordPressClockStrategy implements
    ClockStrategy,
    HasTimezone,
    CanFormatLocalizedDate,
    CanFormatRelativeTime
{
    public function now(): DateTimeImmutable { /* current_datetime() */ }
    public function getTimezone(): DateTimeZone { /* wp_timezone() */ }
    public function formatLocalized(DateTimeImmutable $i, string $f): string { /* wp_date() */ }
    public function relative(DateTimeImmutable $i): string { /* human_time_diff() */ }
}
```

A hypothetical `phpnomad/carbon-integration` would ship a class implementing the much broader Carbon-backed cluster (predicates, arithmetic, boundaries, diff, parsing, formatting). A consumer that needs WordPress's timezone alongside Carbon's diff math binds each interface to the appropriate concrete.

Why a catalog of narrow interfaces
----------------------------------

[](#why-a-catalog-of-narrow-interfaces)

A single fat `TimeStrategy` interface would force every integrator to implement methods their underlying library does not naturally support. A catalog of narrow interfaces lets integrators declare exactly what their library covers, and lets consumers depend only on the capabilities they use. Integrations declare PHPNomad support by implementing the relevant interfaces; consumers compose multiple integrations across libraries as needed.

License
-------

[](#license)

[MIT](LICENSE.txt)

###  Health Score

44

—

FairBetter than 90% of packages

Maintenance91

Actively maintained with recent releases

Popularity20

Limited adoption so far

Community10

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 100% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Every ~15 days

Total

2

Last Release

42d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/9e6206223bd6f2a57b8ac80605b1b5c3521faaec18ad3f20f25fb728a9a13784?d=identicon)[tstandiford](/maintainers/tstandiford)

---

Top Contributors

[![alexstandiford](https://avatars.githubusercontent.com/u/8210827?v=4)](https://github.com/alexstandiford "alexstandiford (5 commits)")

---

Tags

abstractionclockinterfacephpnomadpsr-20timeabstractionclockpsr-20interfacetimephpnomad

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/phpnomad-chrono/health.svg)

```
[![Health](https://phpackages.com/badges/phpnomad-chrono/health.svg)](https://phpackages.com/packages/phpnomad-chrono)
```

###  Alternatives

[symfony/clock

Decouples applications from the system clock

433205.7M428](/packages/symfony-clock)[ecotone/ecotone

Enterprise architecture layer for Laravel and Symfony — CQRS, Event Sourcing, Durable Workflows (Sagas, Orchestrators), Projections, and Outbox messaging via PHP attributes.

564576.7k54](/packages/ecotone-ecotone)[beste/clock

A collection of Clock implementations

7527.5M30](/packages/beste-clock)[flow-php/etl

PHP ETL - Extract Transform Load - Abstraction

378604.0k107](/packages/flow-php-etl)[icecave/chrono

A date &amp; time library that is decoupled from the system clock.

53195.7k7](/packages/icecave-chrono)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
