<?php

// ===== SUPPORTED =====

function mktime ($h ::: int = PHP_INT_MIN, $m ::: int = PHP_INT_MIN, $s ::: int = PHP_INT_MIN,
                $month ::: int = PHP_INT_MIN, $day ::: int = PHP_INT_MIN, $year ::: int = PHP_INT_MIN) ::: int;

function date ($format ::: string, $timestamp ::: int = PHP_INT_MIN) ::: string;

function date_default_timezone_set ($s ::: string) ::: bool;

function gmdate ($format ::: string, $timestamp ::: int = PHP_INT_MIN) ::: string;

function time() ::: int;

function microtime ($get_as_float ::: bool = false) ::: mixed;

function hrtime (bool $as_number = false): mixed; // int[]|int

// ===== UNSUPPORTED =====

/** @kphp-generate-stub-class */
class DateInterval {
  /** @kphp-extern-func-info can_throw generate-stub */
  public function __construct(string $duration);
  /** @kphp-extern-func-info generate-stub */
  public static function createFromDateString(string $datetime): ?DateInterval;
  /** @kphp-extern-func-info generate-stub */
  public function format(string $format): string;
}

/** @kphp-generate-stub-class */
class DateTimeZone {
  /** @kphp-extern-func-info can_throw generate-stub */
  public function __construct(string $timezone);
  /** @kphp-extern-func-info generate-stub */
  public function getName(): string;
}

/** @kphp-generate-stub-class */
interface DateTimeInterface {
  /* Constants */
  const ATOM = "Y-m-d\TH:i:sP";
  const COOKIE = "l, d-M-Y H:i:s T";
  const ISO8601 = "Y-m-d\TH:i:sO";
  const RFC822 = "D, d M y H:i:s O";
  const RFC850 = "l, d-M-y H:i:s T";
  const RFC1036 = "D, d M y H:i:s O";
  const RFC1123 = "D, d M Y H:i:s O";
  const RFC7231 = "D, d M Y H:i:s \G\M\T";
  const RFC2822 = "D, d M Y H:i:s O";
  const RFC3339 = "Y-m-d\TH:i:sP";
  const RFC3339_EXTENDED = "Y-m-d\TH:i:s.vP";
  const RSS = "D, d M Y H:i:s O";
  const W3C = "Y-m-d\TH:i:sP";

  /* Methods */
  public function add(DateInterval $interval): DateTimeInterface;
  public function modify(string $modifier): ?DateTimeInterface;
  public function setDate(int $year, int $month, int $day): DateTimeInterface;
  public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTimeInterface;
  public function setTime(
      int $hour,
      int $minute,
      int $second = 0,
      int $microsecond = 0
  ): DateTimeInterface;
  public function setTimestamp(int $timestamp): DateTimeInterface;
  public function sub(DateInterval $interval): DateTimeInterface;
  public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval;
  public function format(string $format): string;
  public function getOffset(): int;
  public function getTimestamp(): int;
}

/** @kphp-generate-stub-class */
class DateTime implements DateTimeInterface {
  /** @kphp-extern-func-info can_throw generate-stub */
  public function __construct(string $datetime = "now", ?DateTimeZone $timezone = null);
  /** @kphp-extern-func-info generate-stub */
  public function add(DateInterval $interval): DateTime;
  /** @kphp-extern-func-info generate-stub */
  public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): ?DateTime;
  /** @kphp-extern-func-info generate-stub */
  public static function createFromImmutable(DateTimeImmutable $object): DateTime;
  /** @kphp-extern-func-info generate-stub */
  public static function getLastErrors(): array|false;
  /** @kphp-extern-func-info generate-stub */
  public function modify(string $modifier): ?DateTime;
  /** @kphp-extern-func-info generate-stub */
  public function setDate(int $year, int $month, int $day): DateTime;
  /** @kphp-extern-func-info generate-stub */
  public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTime;
  /** @kphp-extern-func-info generate-stub */
  public function setTime(
      int $hour,
      int $minute,
      int $second = 0,
      int $microsecond = 0
  ): DateTime;
  /** @kphp-extern-func-info generate-stub */
  public function setTimestamp(int $timestamp): DateTime;
  /** @kphp-extern-func-info generate-stub */
  public function sub(DateInterval $interval): DateTime;
  /** @kphp-extern-func-info generate-stub */
  public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval;
  /** @kphp-extern-func-info generate-stub */
  public function format(string $format): string;
  /** @kphp-extern-func-info generate-stub */
  public function getOffset(): int;
  /** @kphp-extern-func-info generate-stub */
  public function getTimestamp(): int;
}

/** @kphp-generate-stub-class */
class DateTimeImmutable implements DateTimeInterface {
  /** @kphp-extern-func-info can_throw generate-stub */
  public function __construct(string $datetime = "now", ?DateTimeZone $timezone = null);
  /** @kphp-extern-func-info generate-stub */
  public function add(DateInterval $interval): DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null): ?DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public static function createFromMutable(DateTime $object): DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public static function getLastErrors(): array|false;
  /** @kphp-extern-func-info generate-stub */
  public function modify(string $modifier): ?DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public function setDate(int $year, int $month, int $day): DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public function setISODate(int $year, int $week, int $dayOfWeek = 1): DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public function setTime(
      int $hour,
      int $minute,
      int $second = 0,
      int $microsecond = 0
  ): DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public function setTimestamp(int $timestamp): DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public function sub(DateInterval $interval): DateTimeImmutable;
  /** @kphp-extern-func-info generate-stub */
  public function diff(DateTimeInterface $targetObject, bool $absolute = false): DateInterval;
  /** @kphp-extern-func-info generate-stub */
  public function format(string $format): string;
  /** @kphp-extern-func-info generate-stub */
  public function getOffset(): int;
  /** @kphp-extern-func-info generate-stub */
  public function getTimestamp(): int;
}

define('DATE_ATOM', "Y-m-d\TH:i:sP");
define('DATE_COOKIE', "l, d-M-y H:i:s T");
define('DATE_ISO8601', "Y-m-d\TH:i:sO");
define('DATE_RFC822', "D, d M y H:i:s O");
define('DATE_RFC850', "l, d-M-y H:i:s T");
define('DATE_RFC1036', "D, d M y H:i:s O");
define('DATE_RFC1123', "D, d M Y H:i:s O");
define('DATE_RFC2822', "D, d M Y H:i:s O");
define('DATE_RFC3339', "Y-m-d\TH:i:sP");
define('DATE_RSS', "D, d M Y H:i:s O");
define('DATE_W3C', "Y-m-d\TH:i:sP");

/** @kphp-extern-func-info generate-stub */
function date_default_timezone_get() ::: string;
/** @kphp-extern-func-info generate-stub */
function getdate ($timestamp ::: int = PHP_INT_MIN) ::: mixed[];
/** @kphp-extern-func-info generate-stub */
function gmmktime ($h ::: int = PHP_INT_MIN, $m ::: int = PHP_INT_MIN, $s ::: int = PHP_INT_MIN, $month ::: int = PHP_INT_MIN, $day ::: int = PHP_INT_MIN, $year ::: int = PHP_INT_MIN) ::: int;

/** @kphp-extern-func-info generate-stub */
function localtime ($timestamp ::: int = PHP_INT_MIN, $is_associative ::: bool = false) ::: mixed[];
/** @kphp-extern-func-info generate-stub */
function strftime ($format ::: string, $timestamp ::: int = PHP_INT_MIN) ::: string;
/** @kphp-extern-func-info generate-stub */
function strtotime ($time ::: string, $timestamp ::: int = PHP_INT_MIN) ::: int | false;


/** @kphp-extern-func-info generate-stub */
function checkdate ($month ::: int, $day ::: int, $year ::: int) ::: bool;