<?php

class DateTimeImmutable implements DateTimeInterface
{
    public function __construct(string $datetime = "now", DateTimeZone $timezone = null) {}

    /**
     * @psalm-mutation-free
     * @return static|false
     */
    public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null) {}

    /**
     * @psalm-mutation-free
     *
     * @param string $format
     *
     * @return ($format is non-empty-string ? non-empty-string : string)
     */
    public function format($format) {}

    /**
     * @psalm-mutation-free
     * @return DateTimeZone
     */
    public function getTimezone() {}

    /**
     * @psalm-mutation-free
     * @return int
     */
    public function getOffset() {}

    /**
     * @psalm-mutation-free
     * @return int
     */
    public function getTimestamp() {}

    /**
     * @psalm-mutation-free
     * @param bool $absolute
     * @return DateInterval
     */
    public function diff(DateTimeInterface $targetObject, $absolute = false) {}

    /**
     * @psalm-mutation-free
     * @return static|false
     */
    public function modify(string $modifier) {}

    /**
     * @psalm-mutation-free
     * @return static
     */
    public function add(DateInterval $interval) {}

    /**
     * @psalm-mutation-free
     * @return static

     */
    public function sub(DateInterval $interval) {}

    /**
     * @psalm-mutation-free
     * @return static
     */
    public function setTimezone(DateTimeZone $timezone) {}

    /**
     * @psalm-mutation-free
     * @return static
     */
    public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0) {}

    /**
     * @psalm-mutation-free
     * @return static
     */
    public function setDate(int $year, int $month, int $day) {}

    /**
     * @psalm-mutation-free
     * @return static
     */
    public function setISODate(int $year, int $week, int $dayOfWeek = 1) {}

    /**
     * @psalm-mutation-free
     * @return static
     */
    public function setTimestamp(int $unixtimestamp) {}

    /**
     * @psalm-mutation-free
     * @return static
     */
    public static function createFromMutable(DateTime $object) {}
}

/**
 * @psalm-immutable
 */
class DateTimeZone
{
    public function __construct(string $timezone) {}
}

/**
 * @psalm-immutable
 *
 * @template-covariant Start of string|DateTimeInterface
 * @implements Traversable<int, DateTimeInterface>
 */
class DatePeriod implements Traversable
{
    const EXCLUDE_START_DATE = 1;
    /**
     * @param Start $start
     * @param (Start is string ? 0|self::EXCLUDE_START_DATE : DateInterval) $interval
     * @param (Start is string ? never : DateTimeInterface|positive-int) $end
     * @param (Start is string ? never : 0|self::EXCLUDE_START_DATE) $options
     */
    public function __construct($start, $interval = 0, $end = 1, $options = 0) {}
}

/**
 * @psalm-taint-specialize
 */
interface Throwable
{
    /**
     * @psalm-mutation-free
     */
    public function getMessage() : string;

    /**
     * @psalm-mutation-free
     *
     * @return int|string https://www.php.net/manual/en/throwable.getcode.php
     */
    public function getCode();

    /**
     * @psalm-mutation-free
     */
    public function getFile() : string;

    /**
     * @psalm-mutation-free
     */
    public function getLine() : int;

    /**
     * @psalm-mutation-free
     * @return list<array{file?:string,line?:int,function?:string,class?:class-string,type?:'::'|'->',args?:array<mixed>}>
     */
    public function getTrace() : array;

    /**
     * @psalm-mutation-free
     */
    public function getPrevious() : ?Throwable;

    /**
     * @psalm-mutation-free
     * @psalm-taint-source input
     */
    public function getTraceAsString() : string;

    /**
     * @return string
     * @psalm-taint-source input
     */
    public function __toString();
}

/**
 * @psalm-taint-specialize
 */
class Exception implements Throwable
{
    /**
     * @var string
     */
    protected $message = '';

    /**
     * @var int
     */
    protected $code = 0;

    /**
     * @var string
     */
    protected $file = '';

    /**
     * @var int
     */
    protected $line = 0;

    /**
     * @psalm-external-mutation-free
     * @param string $message
     * @param int $code
     * @param Throwable $previous
     */
    public function __construct($message = "", $code = 0, Throwable $previous = null) {}

    /**
     * @psalm-mutation-free
     */
    public final function getMessage() : string {}

    /**
     * @psalm-mutation-free
     *
     * @return int|string https://www.php.net/manual/en/throwable.getcode.php
     */
    public final function getCode() {}

    /**
     * @psalm-mutation-free
     */
    public final function getFile(): string {}

    /**
     * @psalm-mutation-free
     */
    public final function getLine(): int {}

    /**
     * @psalm-mutation-free
     * @return list<array{file?:string,line?:int,function?:string,class?:class-string,type?:'::'|'->',args?:array<mixed>}>
     */
    public final function getTrace() : array {}

    /**
     * @psalm-mutation-free
     */
    public final function getPrevious() : ?Throwable {}

    /**
     * @psalm-mutation-free
     * @psalm-taint-source input
     */
    public final function getTraceAsString() : string {}

    /**
     * @return string
     * @psalm-taint-source input
     */
    public function __toString() {}
}

/**
 * @psalm-taint-specialize
 */
class Error implements Throwable
{
    /**
     * @var string
     */
    protected $message = '';

    /**
     * @var int
     */
    protected $code = 0;

    /**
     * @var string
     */
    protected $file = '';

    /**
     * @var int
     */
    protected $line = 0;

    /**
     * @psalm-external-mutation-free
     * @param string $message
     * @param int $code
     * @param Throwable $previous
     */
    public function __construct($message = "", $code = 0, Throwable $previous = null) {}

    /**
     * @psalm-mutation-free
     */
    public final function getMessage() : string {}

    /**
     * @psalm-mutation-free
     */
    public final function getCode(): int {}

    /**
     * @psalm-mutation-free
     */
    public final function getFile(): string {}

    /**
     * @psalm-mutation-free
     */
    public final function getLine(): int{}

    /**
     * @psalm-mutation-free
     * @return list<array{file?:string,line?:int,function?:string,class?:class-string,type?:'::'|'->',args?:array<mixed>}>
     */
    public final function getTrace() : array {}

    /**
     * @psalm-mutation-free
     */
    public final function getPrevious() : ?Throwable {}

    /**
     * @psalm-mutation-free
     * @psalm-taint-source input
     */
    public final function getTraceAsString() : string {}

    /**
     * @return string
     * @psalm-taint-source input
     */
    public function __toString() {}
}
