Clocks

System time based

SystemClock

Arokettu\Clock\SystemClock

Note

Can be installed separately as arokettu/system-clock. See The System Clock Package.

A basic system clock:

<?php

$clock = new \Arokettu\Clock\SystemClock();
// optionally with a timezone
$clock = new \Arokettu\Clock\SystemClock(new DateTimeZone('Europe/Tallinn'));

$clock->now(); // whatever time is now

ShiftedClock

Arokettu\Clock\ShiftedClock

A system clock with a constant time shift:

<?php

$shift = DateInterval::createFromDateString('1 week ago');
$clock = new \Arokettu\Clock\ShiftedClock($shift);
// optionally with a timezone
$clock = new \Arokettu\Clock\ShiftedClock($shift, new DateTimeZone('Europe/Tallinn'));
// shorter form
$clock = \Arokettu\Clock\ShiftedClock::fromDateString('1 week ago', new DateTimeZone('Europe/Tallinn'));

$clock->now(); // exactly a week ago

Abstract time based

StaticClock

Arokettu\Clock\StaticClock

Returns a specific time that can be changed manually:

<?php

$clock = new \Arokettu\Clock\StaticClock(); // 'now'
// or a specific time
$clock = new \Arokettu\Clock\StaticClock(new DateTimeImmutable('2007-01-01'));
// or short
$clock = \Arokettu\Clock\StaticClock::fromDateString('2007-01-01');
// or timestamp
$clock = \Arokettu\Clock\StaticClock::fromTimestamp(1167609600);

$clock->now(); // happy new 2007

$clock->set(new DateTimeImmutable('2015-10-21')); // back to the future

MutableClock

Arokettu\Clock\MutableClock

A clock that exposes a regular mutable DateTime that can be manipulated:

<?php

// initialize by 'now'
$clock = new \Arokettu\Clock\MutableClock();
// initialize by date time
$clock = new \Arokettu\Clock\MutableClock(new DateTimeImmutable());
// initialize by expression
$clock = \Arokettu\Clock\MutableClock::fromDateString('yesterday');
// initialize by timestamp
$clock = \Arokettu\Clock\MutableClock::fromTimestamp(1_500_000_000);
// attach to a DateTime instance
$dateTime = new DateTime();
$clock = (new \Arokettu\Clock\MutableClock())->setInstance($dateTime);

// use the attached instance
$dateTime->setDate(2022, 03, 03);
$dateTime->setTime(12, 00, 00);

$clock->now(); // 2022-03-03T12:00:00

// or use the exposed property

$clock->dateTime->modify('+1 day');

$clock->now(); // 2022-03-03T12:00:00

TickingClock

Arokettu\Clock\TickingClock

A clock that advances for a DateInterval value on every call:

<?php

$step = DateInterval::createFromDateString('+1 minute');
// move forward by 1 minute from now
$clock = new \Arokettu\Clock\TickingClock($step);
// same thing in 1 step
$clock = \Arokettu\Clock\TickingClock::fromDateString('+1 minute');

// optionally with an initial time
$time = new DateTime('2022-02-03 12:34');
// move forward by 1 minute from 2022-02-03 12:34:00
$clock = new \Arokettu\Clock\TickingClock($step, $time);
// same thing in 1 step
$clock = \Arokettu\Clock\TickingClock::fromDateString('+1 minute', '2022-02-03 12:34');

$clock->now(); // 2022-02-03T12:34:00
$clock->now(); // 2022-02-03T12:35:00

CallbackClock

Arokettu\Clock\CallbackClock

A clock that returns any time generated by a closure:

<?php

// simple callback
$clock = new \Arokettu\Clock\CallbackClock(function () {
    return new DateTimeImmutable();
});
// generator also supported
$clock = new \Arokettu\Clock\CallbackClock(function () {
    while (true) {
        yield new DateTimeImmutable();
    }
});
// a way to pass an iterable
$values = [
    new DateTimeImmutable(),
    new DateTimeImmutable(),
    new DateTimeImmutable(),
];
$clock = new \Arokettu\Clock\CallbackClock(fn () => yield from $values);

$clock->now(); // whatever callback returns

Note

You can do a similar logic without any library by using an anonymous class:

<?php

$clock = new class implements \Psr\Clock\ClockInterface {
    public function now(): DateTimeImmutable
    {
        // your logic here
    }
};

Wrappers

Rounding clock

Added in version 1.1/2.1.

Arokettu\Clock\RoundingClock

A clock that can truncate another clock to a certain precision:

<?php

use Arokettu\Clock\RoundingClock;
use Arokettu\Clock\StaticClock;

$innerClock = new StaticClock(new DateTime('2012-03-04 5:06:07.899999'));

// round to milliseconds
$clock = new RoundingClock($innerClock, RoundingClock::ROUND_MILLISECONDS);
// same as
$clock = RoundingClock::toMilliseconds($innerClock);
echo $clock->now()->format('c \\m\\s: u'), PHP_EOL; // 2012-03-04T05:06:07+00:00 ms: 899000

// round to weeks
$clock = new RoundingClock($innerClock, RoundingClock::ROUND_WEEKS);
// same as
$clock = RoundingClock::toWeeks($innerClock);
echo $clock->now()->format('c'), PHP_EOL; // 2012-02-27T00:00:00+00:00, nearest Monday

Supported precisions:

  • microseconds (RoundingClock::ROUND_MICROSECONDS)

  • milliseconds (RoundingClock::ROUND_MILLISECONDS)

  • seconds (RoundingClock::ROUND_SECONDS)

  • minutes (RoundingClock::ROUND_MINUTES)

  • hours (RoundingClock::ROUND_HOURS)

  • days (RoundingClock::ROUND_DAYS)

  • ISO weeks (RoundingClock::ROUND_WEEKS)

  • months (RoundingClock::ROUND_MONTHS)

  • calendar years (RoundingClock::ROUND_YEARS)

  • ISO years (RoundingClock::ROUND_ISO_YEARS)

Offset Clock

Added in version 1.5/2.5.

Arokettu\Clock\OffsetClock

A wrapper clock with a constant time shift:

<?php

use Arokettu\Clock\OffsetClock;
use Arokettu\Clock\StaticClock;

$shift = DateInterval::createFromDateString('1 week ago');
$clock = new OffsetClock(new StaticClock(), $shift);
// or
$clock = OffsetClock::fromDateString(new StaticClock(), '1 week ago');

$clock->now(); // exactly a week ago