Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Example abstraction that only allows a resolution of "day" for time inside a specific business domain
<?php
declare(strict_types=1);
namespace Core\Domain\Time;
use DateTimeImmutable;
use DateTimeZone;
use Generator;
use Iterator;
use function sprintf;
use Webmozart\Assert\Assert;
/** @psalm-immutable */
final class Day
{
public const FORMAT = '/^(\d{4})-(\d{2})-(\d{2})$/';
/** @var string */
private $date;
private function __construct(string $date)
{
$this->date = $date;
}
/**
* @param string $date in format YYYY-mm-dd
*
* @see Day::FORMAT
*
* @psalm-pure
*/
public static function fromDateString(string $date): self
{
Assert::regex($date, self::FORMAT);
$dateObject = DateTimeImmutable::createFromFormat('Y-m-d', $date, new DateTimeZone('UTC'));
Assert::object($dateObject, sprintf('Given date "%s" does not appear to be a valid date', $date));
Assert::same($date, $dateObject->format('Y-m-d'), sprintf('Given date "%s" does not appear to be a valid date', $date));
return new self($date);
}
public static function fromDate(DateTimeImmutable $date): self
{
return new self($date->format('Y-m-d'));
}
public function equals(self $other): bool
{
return $other->date === $this->date;
}
public function isAfter(self $other): bool
{
return $this->toDateTimeImmutable() > $other->toDateTimeImmutable();
}
public function toDateTimeImmutable(): DateTimeImmutable
{
$dateObject = DateTimeImmutable::createFromFormat('Y-m-d H:i:s.u', $this->date.' 00:00:00.0', new DateTimeZone('UTC'));
Assert::object($dateObject);
return $dateObject;
}
public function toString(): string
{
return $this->date;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment