Skip to content

Instantly share code, notes, and snippets.

What would you like to do?
Example abstraction that only allows a resolution of "day" for time inside a specific business domain
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'));
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