dateTime = clone $dateTime;
$this->dateTimeZone = $dateTime->getTimezone();
}
/**
* Freezes time to a specific point or current time if no time is given.
*
* @param null $date
*/
public static function freeze($date = null)
{
self::$freeze = false;
self::$freezeDate = $date ? new DateTime($date) : self::now();
self::$freeze = true;
}
/**
* Returns current time as a string.
*
* Example:
*
* Clock::freeze('2011-01-02 12:34');
* $result = Clock::nowAsString('Y-m-d');
*
* Result:
*
* 2011-01-02
*
*
* @param string $format
* @return string
*/
public static function nowAsString($format = null)
{
return self::now()->format($format);
}
/**
* Obtains a Clock set to the current time.
* @return Clock
*/
public static function now()
{
$date = new DateTime();
if (self::$freeze) {
$date->setTimestamp(self::$freezeDate->getTimestamp());
$date->setTimezone(self::$freezeDate->getTimezone());
}
return new Clock($date);
}
/**
* Obtains a Clock set to to a specific point.
* @param string $date
* @return Clock
*/
public static function at($date)
{
$dateTime = new DateTime($date);
return new Clock($dateTime);
}
/**
* Obtains a Clock set to to a specific point using Unix timestamp.
* @param int $timestamp
* @return Clock
*/
public static function fromTimestamp($timestamp)
{
$dateTime = new DateTime();
$dateTime->setTimestamp($timestamp);
return new Clock($dateTime);
}
public function getTimestamp()
{
return $this->dateTime->getTimestamp();
}
public function format($format = null)
{
$format = $format ?: 'Y-m-d H:i:s';
return $this->dateTime->format($format);
}
/**
* Converts this object to a DateTime
*
* @return DateTime
*/
public function toDateTime()
{
return $this->dateTime;
}
private function modify($interval)
{
$dateTime = clone $this->dateTime;
return new Clock($dateTime->modify($interval));
}
private function modifyWithDstChangeSupport($interval)
{
$dateTime = clone $this->dateTime;
$dateTimeZone = new DateTimeZone('GMT');
return new Clock($dateTime->setTimezone($dateTimeZone)->modify($interval)->setTimezone($this->dateTimeZone));
}
private function modifyMonths($interval)
{
$dateTime = clone $this->dateTime;
$currentDay = $dateTime->format('j');
$dateTime->modify($interval);
$endDay = $dateTime->format('j');
if ($currentDay != $endDay) {
$dateTime->modify('last day of last month');
}
return new Clock($dateTime);
}
public function minusDays($days)
{
return $this->modify("-$days days");
}
public function minusHours($hours)
{
return $this->modifyWithDstChangeSupport("-$hours hours");
}
public function minusMinutes($minutes)
{
return $this->modifyWithDstChangeSupport("-$minutes minutes");
}
public function minusMonths($months)
{
return $this->modifyMonths("-$months months");
}
public function minusSeconds($seconds)
{
return $this->modifyWithDstChangeSupport("-$seconds seconds");
}
public function minusYears($years)
{
return $this->modify("-$years years");
}
public function plusDays($days)
{
return $this->modify("+$days days");
}
public function plusHours($hours)
{
return $this->modifyWithDstChangeSupport("+$hours hours");
}
public function plusMinutes($minutes)
{
return $this->modifyWithDstChangeSupport("+$minutes minutes");
}
public function plusMonths($months)
{
return $this->modifyMonths("+$months months");
}
public function plusSeconds($seconds)
{
return $this->modifyWithDstChangeSupport("+$seconds seconds");
}
public function plusYears($years)
{
return $this->modify("+$years years");
}
public function isAfter(Clock $other)
{
return $this->getTimestamp() > $other->getTimestamp();
}
public function isBefore(Clock $other)
{
return $this->getTimestamp() < $other->getTimestamp();
}
public function isAfterOrEqualTo(Clock $other)
{
return $this->getTimestamp() >= $other->getTimestamp();
}
public function isBeforeOrEqualTo(Clock $other)
{
return $this->getTimestamp() <= $other->getTimestamp();
}
/**
* @param string|DateTimeZone $timezone
* @return Clock
*/
public function withTimezone($timezone)
{
$dateTime = clone $this->dateTime;
$dateTime->setTimezone(is_string($timezone) ? new DateTimeZone($timezone) : $timezone);
return new Clock($dateTime);
}
/**
* @return DateTimeZone
*/
private function getTimezone()
{
return $this->dateTimeZone;
}
}