[0, 5], "d" => [1, 5], "h" => [1, 0], "m" => [1, 0], "s" => [1, 0], ]; static function compute_dest(int $x, string $u, ?int $y, DateTime $from): array { $dest = DateTime::clone($from); switch ($u) { case "w": if ($x > 0) { $x *= 7; $dest->add(new \DateInterval("P${x}D")); } $w = 7 - intval($dest->format("w")); $dest->add(new \DateInterval("P${w}D")); $u = "h"; break; case "d": $dest->add(new \DateInterval("P${x}D")); $u = "h"; break; case "h": $dest->add(new \DateInterval("PT${x}H")); $u = "m"; break; case "m": $dest->add(new \DateInterval("PT${x}M")); $u = "s"; break; case "s": $dest->add(new \DateInterval("PT${x}S")); $u = null; break; } if ($y !== null && $u !== null) { $h = intval($dest->format("H")); $m = intval($dest->format("i")); switch ($u) { case "h": $dest->setTime($y, 0, 0, 0); break; case "m": $dest->setTime($h, $y, 0, 0); break; case "s": $dest->setTime($h, $m, $y, 0); break; } } $repr = $y !== null? "$x$y$y": "$x"; return [$dest, $repr]; } function __construct($delay, ?DateTimeInterface $from=null) { if ($from === null) $from = new DateTime(); if (is_int($delay)) { [$dest, $repr] = self::compute_dest($delay, "s", null, $from); } elseif (is_string($delay) && preg_match('/^\d+$/', $delay)) { $x = intval($delay); [$dest, $repr] = self::compute_dest($x, "s", null, $from); } elseif (is_string($delay) && preg_match('/^(\d*)([wdhms])(\d*)$/i', $delay, $ms)) { [$x, $u, $y] = [$ms[1], $ms[2], $ms[3]]; $u = strtolower($u); $default = self::DEFAULTS[$u]; if ($x === "") $x = $default[0]; else $x = intval($x); if ($y === "") $y = $default[1]; else $y = intval($y); [$dest, $repr] = self::compute_dest($x, $u, $y, $from); } else { throw new InvalidArgumentException("invalid delay"); } $this->dest = $dest; $this->repr = $repr; } /** @var DateTime */ protected $dest; function getDest(): DateTime { return $this->dest; } /** @var string */ protected $repr; function __toString(): string { return $this->repr; } protected function _getDiff(?DateTimeInterface $now=null): \DateInterval { if ($now === null) $now = new DateTime(); return $this->dest->diff($now); } /** retourner true si le délai imparti est écoulé */ function isElapsed(?DateTimeInterface $now=null): bool { return $this->_getDiff($now)->invert == 0; } /** * retourner l'intervalle entre le moment courant et la destination. * * l'intervalle est négatif si le délai n'est pas écoulé, positif sinon */ function getDiff(?DateTimeInterface $now=null): DateInterval { return new DateInterval($this->_getDiff($now)); } }