2021-02-26 16:16:17 +00:00
< ? php
namespace Safe ;
use Safe\Exceptions\DatetimeException ;
/**
* This class is used to implement a safe version of the DatetimeImmutable class .
* While it technically overloads \DateTimeImmutable for typehint compatibility ,
* it is actually used as a wrapper of \DateTimeImmutable , mostly to be able to overwrite functions like getTimestamp () while still being able to edit milliseconds via setTime () .
*/
class DateTimeImmutable extends \DateTimeImmutable
{
/**
* @ var \DateTimeImmutable
*/
private $innerDateTime ;
/**
* DateTimeImmutable constructor .
* @ param string $time
2022-07-12 19:26:21 +00:00
* @ param \DateTimeZone | null $timezone
2021-02-26 16:16:17 +00:00
* @ throws \Exception
*/
public function __construct ( $time = 'now' , $timezone = null )
{
parent :: __construct ( $time , $timezone );
$this -> innerDateTime = new parent ( $time , $timezone );
}
//switch between regular datetime and safe version
public static function createFromRegular ( \DateTimeImmutable $datetime ) : self
{
$safeDatetime = new self ( $datetime -> format ( 'Y-m-d H:i:s.u' ), $datetime -> getTimezone ()); //we need to also update the wrapper to not break the operators '<' and '>'
$safeDatetime -> innerDateTime = $datetime ; //to make sure we don't lose information because of the format().
return $safeDatetime ;
}
//usefull if you need to switch back to regular DateTimeImmutable (for example when using DatePeriod)
public function getInnerDateTime () : \DateTimeImmutable
{
return $this -> innerDateTime ;
}
/////////////////////////////////////////////////////////////////////////////
// overload functions with false errors
/**
* @ param string $format
* @ param string $time
2022-07-12 19:26:21 +00:00
* @ param \DateTimeZone | null $timezone
2021-02-26 16:16:17 +00:00
* @ throws DatetimeException
*/
public static function createFromFormat ( $format , $time , $timezone = null ) : self
{
2022-07-12 19:26:21 +00:00
$datetime = \DateTimeImmutable :: createFromFormat ( $format , $time , $timezone );
2021-02-26 16:16:17 +00:00
if ( $datetime === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $datetime );
}
/**
* @ param string $format
* @ return string
* @ throws DatetimeException
*/
public function format ( $format ) : string
{
/** @var string|false $result */
$result = $this -> innerDateTime -> format ( $format );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return $result ;
}
/**
2022-07-12 19:26:21 +00:00
* @ param \DateTimeInterface $datetime2
2021-02-26 16:16:17 +00:00
* @ param bool $absolute
2022-07-12 19:26:21 +00:00
* @ return \DateInterval
2021-02-26 16:16:17 +00:00
* @ throws DatetimeException
*/
2022-07-12 19:26:21 +00:00
public function diff ( $datetime2 , $absolute = false ) : \DateInterval
2021-02-26 16:16:17 +00:00
{
/** @var \DateInterval|false $result */
$result = $this -> innerDateTime -> diff ( $datetime2 , $absolute );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return $result ;
}
/**
* @ param string $modify
* @ return DateTimeImmutable
* @ throws DatetimeException
*/
public function modify ( $modify ) : self
{
/** @var \DateTimeImmutable|false $result */
$result = $this -> innerDateTime -> modify ( $modify );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $result ); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable
}
/**
* @ param int $year
* @ param int $month
* @ param int $day
* @ return DateTimeImmutable
* @ throws DatetimeException
*/
public function setDate ( $year , $month , $day ) : self
{
/** @var \DateTimeImmutable|false $result */
$result = $this -> innerDateTime -> setDate ( $year , $month , $day );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $result ); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable
}
/**
* @ param int $year
* @ param int $week
* @ param int $day
* @ return DateTimeImmutable
* @ throws DatetimeException
*/
public function setISODate ( $year , $week , $day = 1 ) : self
{
/** @var \DateTimeImmutable|false $result */
$result = $this -> innerDateTime -> setISODate ( $year , $week , $day );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $result ); //we have to recreate a safe datetime because modify create a new instance of \DateTimeImmutable
}
/**
* @ param int $hour
* @ param int $minute
* @ param int $second
* @ param int $microseconds
* @ return DateTimeImmutable
* @ throws DatetimeException
*/
public function setTime ( $hour , $minute , $second = 0 , $microseconds = 0 ) : self
{
/** @var \DateTimeImmutable|false $result */
$result = $this -> innerDateTime -> setTime ( $hour , $minute , $second , $microseconds );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $result );
}
/**
* @ param int $unixtimestamp
* @ return DateTimeImmutable
* @ throws DatetimeException
*/
public function setTimestamp ( $unixtimestamp ) : self
{
/** @var \DateTimeImmutable|false $result */
$result = $this -> innerDateTime -> setTimestamp ( $unixtimestamp );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $result );
}
/**
2022-07-12 19:26:21 +00:00
* @ param \DateTimeZone $timezone
2021-02-26 16:16:17 +00:00
* @ return DateTimeImmutable
* @ throws DatetimeException
*/
public function setTimezone ( $timezone ) : self
{
/** @var \DateTimeImmutable|false $result */
$result = $this -> innerDateTime -> setTimezone ( $timezone );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $result );
}
/**
2022-07-12 19:26:21 +00:00
* @ param \DateInterval $interval
2021-02-26 16:16:17 +00:00
* @ return DateTimeImmutable
* @ throws DatetimeException
*/
public function sub ( $interval ) : self
{
/** @var \DateTimeImmutable|false $result */
$result = $this -> innerDateTime -> sub ( $interval );
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return self :: createFromRegular ( $result );
}
/**
* @ throws DatetimeException
*/
public function getOffset () : int
{
/** @var int|false $result */
$result = $this -> innerDateTime -> getOffset ();
if ( $result === false ) {
throw DatetimeException :: createFromPhpError ();
}
return $result ;
}
//////////////////////////////////////////////////////////////////////////////////////////
//overload getters to use the inner datetime immutable instead of itself
/**
2022-07-12 19:26:21 +00:00
* @ param \DateInterval $interval
2021-02-26 16:16:17 +00:00
* @ return DateTimeImmutable
*/
public function add ( $interval ) : self
{
return self :: createFromRegular ( $this -> innerDateTime -> add ( $interval ));
}
/**
2022-07-12 19:26:21 +00:00
* @ param \DateTime $dateTime
2021-02-26 16:16:17 +00:00
* @ return DateTimeImmutable
*/
public static function createFromMutable ( $dateTime ) : self
{
2022-07-12 19:26:21 +00:00
$date = \DateTimeImmutable :: createFromMutable ( $dateTime );
return self :: createFromRegular ( $date );
2021-02-26 16:16:17 +00:00
}
/**
* @ param mixed [] $array
* @ return DateTimeImmutable
*/
public static function __set_state ( $array ) : self
{
return self :: createFromRegular ( parent :: __set_state ( $array ));
}
2022-07-12 19:26:21 +00:00
public function getTimezone () : \DateTimeZone
2021-02-26 16:16:17 +00:00
{
return $this -> innerDateTime -> getTimezone ();
}
public function getTimestamp () : int
{
return $this -> innerDateTime -> getTimestamp ();
}
}