/**
  * Constructor.
  *
  * @param string|DateTime|PHPDateTime|int|null $dateTime [optional] The date and time as a string, the date and
  *     time as DateTime or PHPDateTime instance, the UNIX timestamp as an integer, or null to use the current time.
  * @param DateTimeZone|PHPDateTimeZone|string|DateTime|PHPDateTime $timezone [optional] The timezone the specified
  *     time is in, or null to use the default timezone. A DateTime or PHPDateTime instance to use it's timezone.
  *
  * @throws InvalidDateTimeZoneException Throws InvalidDateTimeZoneException if the timezone is invalid.
  */
 public function __construct($dateTime = null, $timezone = null)
 {
     // Handle DateTime instances
     if ($dateTime instanceof self) {
         // Construct the parent object with the proper properties
         parent::__construct($dateTime->toCompleteString(), $dateTime->getTimezone());
         return $this;
     }
     // Handle PHPDateTime instances
     if ($dateTime instanceof parent) {
         // Construct the parent object with the proper properties
         parent::__construct($dateTime->format(self::DEFAULT_FORMAT_COMPLETE), $dateTime->getTimezone());
         return $this;
     }
     // Check whether this is a timestamp
     if (is_int($dateTime)) {
         // Parse the timezone if it isn't null and make sure it's valid
         if ($timezone !== null) {
             if (($timezone = DateTimeZoneUtils::parse($timezone, null)) === null) {
                 throw new InvalidDateTimeZoneException('The given timezone is invalid');
             }
         }
         // Construct the parent object with the timestamp
         parent::__construct('@' . $dateTime, $timezone);
         // Set the proper timezone, and return this instance
         return $this->setTimezone($timezone);
     }
     // Check whether we should use the now time
     if (empty($dateTime) || StringUtils::equals($dateTime, 'now', false, true)) {
         // Return a new instance of the mock time if set, or the regular now time
         if (static::hasMockNow()) {
             // Get the mock now time
             $dateTime = static::getMockNow()->copy();
             // Shift the timezone
             if ($timezone !== null) {
                 $dateTime->setTimezone($timezone);
             }
         } else {
             $dateTime = 'now';
         }
     }
     // Parse the timezone if it isn't null and make sure it's valid
     if ($timezone !== null) {
         if (($timezone = DateTimeZoneUtils::parse($timezone, null)) === null) {
             throw new InvalidDateTimeZoneException('The given timezone is invalid');
         }
     }
     // Check whether the time contains relative keywords
     if (static::hasRelativeKeywords($dateTime)) {
         // Get a new DateTime instance, and modify the date and time according to the time parameter
         $dateTime = static::now($timezone)->modify($dateTime);
         // Shift the timezone if it's set
         // TODO: Should we do this, or is this done already with the 'now()' method?
         // TODO: Is this code below already done with the above statement?
         if ($timezone !== null && !$timezone->equals(static::getMockNow())) {
             $dateTime->setTimezone($timezone);
         } else {
             $timezone = $dateTime->getTimezone();
         }
         // Update the time parameter with the modified time
         $dateTime = $dateTime->toCompleteString();
     }
     // Construct the parent object
     parent::__construct($dateTime, $timezone);
     return $this;
 }