PHPackages                             raigu/psr20-clock-testdoubles - 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. [Testing &amp; Quality](/categories/testing)
4. /
5. raigu/psr20-clock-testdoubles

ActiveLibrary[Testing &amp; Quality](/categories/testing)

raigu/psr20-clock-testdoubles
=============================

Test Doubles for PSR-20 clock interface

00PHP

Since Sep 2Pushed 4y ago1 watchersCompare

[ Source](https://github.com/raigu/psr20-clock-testdoubles)[ Packagist](https://packagist.org/packages/raigu/psr20-clock-testdoubles)[ RSS](/packages/raigu-psr20-clock-testdoubles/feed)WikiDiscussions main Synced 1mo ago

READMEChangelogDependenciesVersions (1)Used By (0)

[![Latest Stable Version](https://camo.githubusercontent.com/2876bc864c6afab1c88fa6054c228a30d5b9e2136bb86997b07b528cdd02e448/687474703a2f2f706f7365722e707567782e6f72672f72616967752f70737232302d636c6f636b2d74657374646f75626c65732f76)](https://packagist.org/packages/raigu/psr20-clock-testdoubles)[![Latest Unstable Version](https://camo.githubusercontent.com/a32240c8e89795ea45556a2ba94481ea8aef9c445c8e140d2db9ccd6fa13f184/687474703a2f2f706f7365722e707567782e6f72672f72616967752f70737232302d636c6f636b2d74657374646f75626c65732f762f756e737461626c65)](https://packagist.org/packages/raigu/psr20-clock-testdoubles)[![Fallows SemVer](https://camo.githubusercontent.com/0ba7a49bc642a7fa1e7c2b21f034148f17652edb537d5aed7f0dfbe3259f8cc4/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f53656d5665722d322e302e302d677265656e)](https://semver.org/spec/v2.0.0.html)[![build](https://github.com/raigu/psr20-clock-testdoubles/workflows/build/badge.svg)](https://github.com/raigu/psr20-clock-testdoubles/actions)[![codecov](https://camo.githubusercontent.com/0fea87883e6f1fccf4db69c825724be418017aee444ab5a0b20301ad8e2e5558/68747470733a2f2f636f6465636f762e696f2f67682f72616967752f70737232302d636c6f636b2d74657374646f75626c65732f6272616e63682f6d61696e2f67726170682f62616467652e7376673f746f6b656e3d394444303434544e3732)](https://codecov.io/gh/raigu/psr20-clock-testdoubles)[![Mutation testing badge](https://camo.githubusercontent.com/ce9e5a0b8d335168bef45ccd7c02a542ca608f3819ef599f3c20298d9ea122bd/68747470733a2f2f696d672e736869656c64732e696f2f656e64706f696e743f7374796c653d666c61742675726c3d687474707325334125324625324662616467652d6170692e737472796b65722d6d757461746f722e696f2532466769746875622e636f6d253246726169677525324670737232302d636c6f636b2d74657374646f75626c65732532466d61696e)](https://dashboard.stryker-mutator.io/reports/github.com/raigu/psr20-clock-testdoubles/main)[![License: MIT](https://camo.githubusercontent.com/08cef40a9105b6526ca22088bc514fbfdbc9aac1ddbf8d4e6c750e3a88a44dca/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f4c6963656e73652d4d49542d626c75652e737667)](LICENSE)

Test Doubles for PSR-20 clock

Unstable because the PSR-20 is not officially released yet.

Compatibility
=============

[](#compatibility)

- PHP 7.4, ^8.0
- psr/clock==@dev

Changes
=======

[](#changes)

[./CHANGELOG.md](./CHANGELOG.md)

Install
=======

[](#install)

```
$ composer require --dev raigu/psr20-clock-testdoubles
```

Test Doubles
============

[](#test-doubles)

FrozenClock
-----------

[](#frozenclock)

Clock frozen in time. It always returns the same time now matter how many times the `now` is called.

```
// creating with current system date and time
$clock = new \Raigu\TestDouble\Psr20\FrozenClock;

// creating with predefined date and time at
$clock = new \Raigu\TestDouble\Psr20\FrozenClock(
    new DateTimeImmutable('2020-01-02')
);
```

TimeTravelClock
---------------

[](#timetravelclock)

Clock that acts like normal clock but has a shift in time if given.

```
// By default, acts like normal clock.
$clock = new \Raigu\TestDouble\Psr20\TimeTravelClock();
$moment = $clock->now();
sleep(2);
// after two seconds the TimeTravelClock is also moved forward.
assert($moment->add(new DateInterval('PT2S'))->getTimestamp() === $clock->now()->getTimestamp());

// Moving to the specific date and time in the future or past:
$clock->travelInTime(new DateTimeImmutable('2020-01-02'));
assert($clock->now()->format('Y-m-d') === '2020-01-02');

// Move by the specific interval to the future
$clock->travelInTimeByInterval(new DateInterval('P10D'));
assert($clock->now()->format('Y-m-d') === '2020-01-12');

// Move by the specific interval to the past
$clock->travelInTimeByInterval(DateInterval::createFromDateString('-1 day'));
assert($clock->now()->format('Y-m-d') === '2020-01-11');
```

The `TimeTravelClock` implements the Decorator pattern by wrapping a clock implementation. By default, it uses a system clock implementation, but it can be replaced in constructor.

For example, it is possible to create TimeTravelClock that is frozen by using `FrozenClock`:

```
$clock = new \Raigu\TestDouble\Psr20\TimeTravelClock(
    new Raigu\TestDouble\Psr20\FrozenClock()
);
$moment = $clock->now();
sleep(2);
assert($moment->getTimestamp() === $clock->getTimestamp(), 'Does not tick because base clock is frozen.');
```

Testing
=======

[](#testing)

```
$ composer test
$ composer specification
$ composer coverage
```

###  Health Score

14

—

LowBetter than 2% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity0

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity28

Early-stage or recently created project

 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.

### Community

Maintainers

![](https://www.gravatar.com/avatar/82bf3ac844b3984ae4f9965188829da1729ca1e86abd92151406d15896c021b9?d=identicon)[raigu](/maintainers/raigu)

---

Top Contributors

[![raigu](https://avatars.githubusercontent.com/u/3442567?v=4)](https://github.com/raigu "raigu (35 commits)")

---

Tags

clockdoublephppsr-20stubtesttime

### Embed Badge

![Health badge](/badges/raigu-psr20-clock-testdoubles/health.svg)

```
[![Health](https://phpackages.com/badges/raigu-psr20-clock-testdoubles/health.svg)](https://phpackages.com/packages/raigu-psr20-clock-testdoubles)
```

###  Alternatives

[phpspec/prophecy

Highly opinionated mocking framework for PHP 5.3+

8.5k551.7M682](/packages/phpspec-prophecy)[vimeo/psalm

A static analysis tool for finding errors in PHP applications

5.8k77.5M6.7k](/packages/vimeo-psalm)[brianium/paratest

Parallel testing for PHP

2.5k118.8M754](/packages/brianium-paratest)[beberlei/assert

Thin assertion library for input validation in business models.

2.4k96.9M571](/packages/beberlei-assert)[mikey179/vfsstream

Virtual file system to mock the real file system in unit tests.

1.4k108.0M2.7k](/packages/mikey179-vfsstream)[orchestra/testbench

Laravel Testing Helper for Packages Development

2.2k39.1M32.1k](/packages/orchestra-testbench)

PHPackages © 2026

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