diff --git a/php/src/php/time/Delay.php b/php/src/php/time/Delay.php index f1008b2..15aa96f 100644 --- a/php/src/php/time/Delay.php +++ b/php/src/php/time/Delay.php @@ -30,6 +30,11 @@ class Delay { else return new static($delay, $from); } + /** + * pour une durée infinie, l'intervalle est toujours de 1000 ans dans le futur + */ + const INF_INTERVAL = "P1000Y"; + /** valeurs par défaut de x et y pour les unités supportées */ const DEFAULTS = [ "w" => [0, 5], @@ -89,12 +94,9 @@ class Delay { function __construct($delay, ?DateTimeInterface $from=null) { $from = MutableDateTime::with($from)->clone(true); - if ($delay === "INF") { - $dest = $from; - # rajouter 1000 ans pour ne pas dépasser la capacité - #XXX avant, c'était 9999 ans, mais getDest() provoque une exception parce - # que DateTime ne sait pas traiter une valeur flottante - $dest->add(new DateInterval("P1000Y")); + if ($delay === null || $delay === "INF") { + # $dest === null signifie un délai infini + $dest = null; $repr = "INF"; } elseif (is_int($delay)) { [$dest, $repr] = self::compute_dest($delay, "s", null, $from); @@ -118,38 +120,51 @@ class Delay { } function __clone() { - $this->dest = clone $this->dest; + if ($this->dest !== null) { + $this->dest = clone $this->dest; + } } function __serialize(): array { - return [$this->dest->clone(), $this->repr]; + $dest = $this->dest; + if ($dest !== null) $dest = $dest->clone(); + return [$dest, $this->repr]; } function __unserialize(array $data): void { [$dest, $this->repr] = $data; - $this->dest = $dest->clone(true); + if ($dest !== null) $dest = $dest->clone(true); + $this->dest = $dest; } - /** @var MutableDateTime */ - protected $dest; + protected ?MutableDateTime $dest; function getDest(): DateTime { - return $this->dest->clone(); + $dest = $this->dest; + if ($dest === null) { + $dest = new MutableDateTime(); + $dest->add(new \DateInterval(self::INF_INTERVAL)); + } + return $dest->clone(); } function addDuration($duration): self { - if (is_numeric($duration) && $duration < 0) { - $this->dest->sub(DateInterval::with(-$duration)); - } else { - $this->dest->add(DateInterval::with($duration)); + if ($this->dest !== null) { + if (is_numeric($duration) && $duration < 0) { + $this->dest->sub(DateInterval::with(-$duration)); + } else { + $this->dest->add(DateInterval::with($duration)); + } } return $this; } function subDuration($duration): self { - if (is_numeric($duration) && $duration < 0) { - $this->dest->add(DateInterval::with(-$duration)); - } else { - $this->dest->sub(DateInterval::with($duration)); + if ($this->dest !== null) { + if (is_numeric($duration) && $duration < 0) { + $this->dest->add(DateInterval::with(-$duration)); + } else { + $this->dest->sub(DateInterval::with($duration)); + } } return $this; } @@ -161,23 +176,20 @@ class Delay { return $this->repr; } - protected function _getDiff(?DateTimeInterface $now=null): \DateInterval { - $now ??= new \DateTime(); - return $this->dest->diff($now); - } - - /** retourner true si le délai imparti est écoulé */ - function isElapsed(?DateTimeInterface $now=null): bool { - if ($this->repr === "INF") return false; - else 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)); + $dest = $this->dest; + if ($dest !== null) return $dest->diff($now ?? new \DateTime()); + else return new DateInterval("-".self::INF_INTERVAL); + } + + /** retourner true si le délai imparti est écoulé */ + function isElapsed(?DateTimeInterface $now=null): bool { + if ($this->dest === null) return false; + else return $this->getDiff($now)->invert == 0; } } diff --git a/php/src/php/time/TODO.md b/php/src/php/time/TODO.md index f5ff33b..ffa6b2e 100644 --- a/php/src/php/time/TODO.md +++ b/php/src/php/time/TODO.md @@ -1,9 +1,3 @@ # nulib\php\time -* refaire l'implémentation pour les délais INF. c'est un cas particulier qui - n'est jamais atteint. il faut donc implémenter un traitement spécifique dans - chaque méthode (i.e `if ($repr === "INF") { doSomething() }`) - * la destination est toujours 1000 ans dans le futur - * la différence est toujours de 1000 ans - -*- coding: utf-8 mode: markdown -*- vim:sw=4:sts=4:et:ai:si:sta:fenc=utf-8:noeol:binary \ No newline at end of file diff --git a/php/tests/php/time/DelayTest.php b/php/tests/php/time/DelayTest.php index 1b2ef42..b7c1dd2 100644 --- a/php/tests/php/time/DelayTest.php +++ b/php/tests/php/time/DelayTest.php @@ -83,4 +83,19 @@ class DelayTest extends TestCase { $unserialized = unserialize($serialized); self::assertEquals($delay, $unserialized); } + + function testInf() { + $delay = new Delay("INF"); + self::assertSame("INF", strval($delay)); + self::assertFalse($delay->isElapsed()); + + $diff = $delay->getDiff(); + self::assertSame("-P1000YT", strval($diff)); + + $serialized = serialize($delay); + self::assertSame('O:20:"nulib\php\time\Delay":2:{i:0;N;i:1;s:3:"INF";}', $serialized); + echo "serialized: $serialized\n"; + $unserialized = unserialize($serialized); + self::assertEquals($delay, $unserialized); + } }