getSeconds(); } elseif ($time === null || is_int($time)) { $seconds = $time !== null? $time: 0; if ($unit !== null) $seconds *= $unit; } elseif (is_array($time)) { [$h, $m, $s] = $time; $seconds = $h * 3600 + $m * 60 + $s; } elseif (is_string($time) && preg_match(self::PATTERN, $time, $ms)) { $seconds = intval($ms[1]) * 3600 + intval($ms[2]) * 60 + intval($ms[3]); } else { throw ValueException::invalid_value($time, "time"); } return $seconds; } /** * @return int la valeur de l'unité en secondes, pour le constructeur et les * méthodes {@link newu()}, {@link addu()} et {@link subu()} */ function UNIT(): int { return static::UNIT; } const UNIT = self::UNIT_SECONDS; /** @return bool s'il faut garder les heures dans la plage [0, 24h] */ protected function WRAP(): bool { return static::WRAP; } const WRAP = true; function __construct($time=null) { if ($time !== false) { $this->setSeconds(self::parse_time($time, $this->UNIT())); } } /** cet objet est-il l'instance nulle? */ function isNull(): bool { return false; } /** cet objet est-il l'heure indéfinie? */ function isUndef(): bool { return false; } /** * wrapper l'heure pour la garder dans la plage [0h, 24h[ ce qui la rend * propice à l'utilisation comme borne inférieure d'une période */ function wrapStart(): self { $seconds = $this->seconds; while ($seconds < 0) $seconds += 86400; if ($seconds >= 86400) $seconds %= 86400; $this->seconds = $seconds; return $this; } /** * wrapper l'heure pour la garder dans la plage [0h, 24h] ce qui la rend * propice à l'utilisation comme borne supérieure d'une période */ function wrapEnd(): self { $seconds = $this->seconds; while ($seconds < 0) $seconds += 86400; if ($seconds > 86400) $seconds %= 86400; $this->seconds = $seconds; return $this; } protected function afterUpdate(): void { if ($this->WRAP()) $this->wrapEnd(); } /** @var int */ protected $seconds; /** @return int le nombre de secondes */ function getSeconds(): int { return $this->seconds; } /** * mettre à jour cet objet avec le nombre de secondes spécifié * * @return int le nombre de seconde effectif, après correction */ protected function setSeconds(?int $seconds): int { if ($seconds === null) { $hms = date('His'); $seconds = intval(substr($hms, 0, 2)) * 3600 + intval(substr($hms, 2, 2)) * 60 + intval(substr($hms, 4, 2)); } $adjust = $seconds % $this->UNIT(); if ($seconds < 0) $adjust = -$adjust; $seconds -= $adjust; $this->seconds = $seconds; $this->afterUpdate(); return $this->seconds; } /** formatter cette heure pour affichage */ function format(?string $format=null): string { if ($format === null) $format = static::FORMAT; $v = $this->seconds; $h = intdiv($v, 3600); $v = $v % 3600; $m = intdiv($v, 60); $s = $v % 60; $searches = [ "HH", "H", "MM", "M", "SS", "S", ]; $replaces = [ sprintf("%02u", $h), strval($h), sprintf("%02u", $m), strval($m), sprintf("%02u", $s), strval($s), ]; return str_replace($searches, $replaces, $format); } function __toString(): string { return $this->format(); } /** @return int le nombre d'unités */ function getu(): int { return intdiv($this->seconds, $this->UNIT()); } /** créer une nouvelle heure avec le nombre d'unités spécifiées */ function newu(int $count): self { if ($this->isNull()) return self::null(); if ($this->isUndef()) return self::undef(); $clone = clone $this; $clone->setSeconds($count * $this->UNIT()); return $clone; } /** créer une nouvelle heure en ajoutant à cette heure le nombre d'unités spécifiées */ function addu(int $count): self { if ($this->isNull()) return self::null(); if ($this->isUndef()) return self::undef(); $clone = clone $this; $clone->setSeconds($clone->getSeconds() + $count * $this->UNIT()); return $clone; } /** créer une nouvelle heure en soustrayant à cette heure le nombre d'unités spécifiées */ function subu(int $count): self { if ($this->isNull()) return self::null(); if ($this->isUndef()) return self::undef(); $clone = clone $this; $clone->setSeconds($clone->getSeconds() - $count * $this->UNIT()); return $clone; } /** mettre à jour cette heure avec le nombre de secondes d'une autre instance */ function set(Time $time): self { $this->setSeconds($time->getSeconds()); return $this; } /** créer une nouvelle heure copie de l'heure spécifiée */ function new(Time $time): self { if ($this->isNull()) return self::null(); if ($this->isUndef() || $time->isUndef()) return self::undef(); $clone = clone $this; $clone->setSeconds($time->getSeconds()); return $clone; } /** créer une nouvelle heure en ajoutant à cette heure l'heure spécifiée */ function add(Time $time): self { if ($this->isNull()) return self::null(); if ($this->isUndef() || $time->isUndef()) return self::undef(); $clone = clone $this; $clone->setSeconds($clone->getSeconds() + $time->getSeconds()); return $clone; } /** créer une nouvelle heure en soustrayant à cette heure l'heure spécifiée */ function sub(Time $time): self { if ($this->isNull()) return self::null(); if ($this->isUndef() || $time->isUndef()) return self::undef(); $clone = clone $this; $clone->setSeconds($clone->getSeconds() - $time->getSeconds()); return $clone; } /** * comparer avec l'heure spécifiée. retourner une valeur négative, égale à * zéro ou positive suivant le résultat de la comparaison */ function cmp(Time $time): int { return $this->seconds - $time->getSeconds(); } /** tester si cette heure est avant l'heure spécifiée */ function before(Time $other): bool { return $this->seconds <= $other->getSeconds(); } /** tester si cette heure est après l'heure spécifiée */ function after(Time $other): bool { return $this->seconds >= $other->getSeconds(); } ############################################################################# private static $null; /** * @return Time une instance immutable représentant la valeur nulle. * * En général, on utilise directement null pour indiquer qu'il n'y a pas de * valeur, mais cette instance peut etre utilisée dans les contextes où null * n'est pas autorisé */ static final function null(): self { if (self::$null === null) { self::$null = new class extends Time { function __construct() { parent::__construct(false); $this->seconds = 0; } function isNull(): bool { return true; } function wrapStart(): Time { throw IllegalAccessException::immutable_object(); } function wrapEnd(): Time { throw IllegalAccessException::immutable_object(); } function setSeconds(?int $seconds): int { throw IllegalAccessException::immutable_object(); } function __toString(): string { return ""; } }; } return self::$null; } private static $undef; /** * @return Time une instance immutable représentant une heure non définie, * (c'est à dire qu'on ne sait pas de quelle heure il s'agit). Cette * instance peut etre utilisée s'il faut pouvoir faire la différence entre * pas de valeur (null) et une valeur non définie (false) */ static final function undef(): self { if (self::$undef === null) { self::$undef = new class extends Time { function __construct() { parent::__construct(false); $this->seconds = 0; } function isUndef(): bool { return true; } function wrapStart(): Time { throw IllegalAccessException::immutable_object(); } function wrapEnd(): Time { throw IllegalAccessException::immutable_object(); } function setSeconds(?int $seconds): int { throw IllegalAccessException::immutable_object(); } function __toString(): string { return ""; } }; } return self::$undef; } }