alex-patterson-webdev / date-time
DateTime factory components for PHP
Installs: 1 801
Dependents: 3
Suggesters: 0
Security: 0
Stars: 1
Watchers: 1
Forks: 0
Open Issues: 1
pkg:composer/alex-patterson-webdev/date-time
Requires
- php: >=8.1
- psr/clock: ^1.0.0
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.6.0
- phpspec/prophecy: ^1.15.0
- phpstan/phpstan: ^1.4.8
- phpunit/phpunit: ^9.5
- squizlabs/php_codesniffer: ^3.6
Provides
This package is auto-updated.
Last update: 2025-10-06 19:06:52 UTC
README
Arp\DateTime
About
The library provides implementations of the PSR-20 Clock ClockInterface and a
number of factories which abstract the creation of native PHP DateTime objects.
Installation
Installation via composer.
require alex-patterson-webdev/date-time ^0.6
Theory
By abstracting the creation of Date Time objects behind a simple collection of interfaces, we can allow developers to treat date time creation as a service.
The Arp\DateTime\DateTimeFactory can be used as a replacement for any code that would normally require new \DateTime().
Consider an example UserService::updateLastLoginDate() method; designed to update a user's last login date with the current date and time.
class UserService
{
public function updateLastLoginDate($user)
{
$user->setLastLoginDate(new \DateTime());
}
}
This approach, while simple, would be difficult to assert a value for the 'current time' in a unit test. Alternatively, we could update this
example to include the DateTimeFactory, which would abstract the creation of the \DateTime object.
class UserService
{
private DateTimeFactoryInterface $dateTimeFactory;
public function __construct(DateTimeFactoryInterface $dateTimeFactory)
{
$this->dateTimeFactory = $dateTimeFactory;
}
public function updateLastLoginDate($user)
{
$user->setLastLoginDate($this->dateTimeFactory->createDateTime());
}
}
The approach has a number of notable benefits
- The
DateTimeFactoryInterfaceprovides an abstraction for all\DateTimeobject creation. - Unit testing and asserting date time values becomes very easy as we can now mock the return value of
$this->dateTimeFactory->createDateTime(). - Rather than returning a boolean
falsewhen unable to create date objects, the factory classes will instead throw aDateTimeException.
DateTimeFactoryInterface
The DateTimeFactoryInterface exposes two public methods, createDateTime() and createFromFormat(). The method signatures are
similar to the PHP \DateTime methods.
interface DateTimeFactoryInterface
{
/**
* @throws DateTimeFactoryException
*/
public function createDateTime(?string $spec = null, $timeZone = null): \DateTimeInterface;
/**
* @throws DateTimeFactoryException
*/
public function createFromFormat(string $format, string $spec, $timeZone = null): \DateTimeInterface;
}
The createDateTime() method can replace uses of \DateTime::__construct.
The createFromFormat() method can replace uses of \DateTime::createFromFormat().
There are however a number of differences to consider.
- The methods of the interface are defined as non-static and require a factory instance to invoke them.
- A
DateTimeFactoryExceptionwill be thrown if the\DateTimeinstance cannot be created. - The
$specparameter ofcreateDateTime()acceptsnull. Passingnullis equivalent to using the current date and time, i.e.now. - The
$timeZonecan be either astringor\DateTimeZoneinstance. If a supportedDateTimeZonestring is provided, the\DateTimeZoneinstance will be created internally; otherwise aDateTimeFactoryExceptionwill be thrown.
Implementations
The package provides two default implementations of the DateTimeFactoryInterface.
DateTimeFactorycan be used to create\DateTimeinstances.DateTimeImmutableFactorycan be used to create\DateTimeImmutibleinstances
Because both classes implement the DateTimeFactoryInterface, they can be used in the same way.
$dateTimeFactory = new \Arp\DateTime\DateTimeFactory();
$dateTimeImmutableFactory = new \Arp\DateTime\DateTimeImmutableFactory();
try {
/** @var \DateTime $dateTime **/
$dateTime = $dateTimeFactory->createDateTime();
/** @var \DateTimeImmutable $dateTimeImmutable **/
$dateTimeImmutable = $dateTimeImmutableFactory->createDateTime();
} catch (\DateTimeFactoryException $e) {
// if the date creation fails
}
DateTimeZoneFactory
\DateTimeZone instances can be created using any class that implements Arp\DateTime\DateTimeZoneFactoryInterface.
/*
* @throws DateTimeZoneFactoryException
*/
public function createDateTimeZone(string $spec): \DateTimeZone;
The default implementation of the interface is Arp\DateTime\DateTimeZoneFactory.
$dateTimeZoneFactory = new \Arp\DateTime\DateTimeZoneFactory();
try {
/** @var \DateTimeZone $dateTimeZone **/
$dateTimeZone = $dateTimeZoneFactory->createDateTimeZone('UTC');
} catch (\DateTimeZoneFactoryException $e) {
// The \DateTimeZone() could not be created
}
PSR-20 ClockInterface
Using the PSR standards provides implementing projects interoperability between other packages by creating a standard way of accessing the current time.
The package provides a number of implementations of the PSR-20 Clock interface.
Arp\DateTime\Psr\ClockA default implementation ofPsr\Clock\ClockInterfacewhere a desired DateTimeZone can be provided.Arp\DateTime\Psr\SystemClockAn implementation ofPsr\Clock\ClockInterfacethat will always provide the current time using the configured system timezone.Arp\DateTime\Psr\FixedClockAn implementation ofPsr\Clock\ClockInterfacethat will always return a fixed\DateTimeImmutable; which can be useful in testing.
Example usages
use Arp\DateTime\DateTimeImmutableFactory;
use Arp\DateTime\Psr\SystemClock;
// Fetch the current time using the UTC timezone
$clock = new Clock(new DateTimeImmutableFactory(), 'UTC');
$utcTime = $clock->now();
// Fetch the current time using the systems configured timezone
$clock = new SystemClock(new DateTimeImmutableFactory());
$systemTime = $clock->now();
// Calls to FixedClock::now() will always return the same time provided in the constructor
$clock = new FixedClock(new \DateTimeImmutable());
$fixedTime = $clock->now();
Unit tests
Unit tests can be executed using PHPUnit from the application root directory.
php vendor/bin/phpunit