modifs.mineures sans commentaires
This commit is contained in:
		
							parent
							
								
									81f666f90e
								
							
						
					
					
						commit
						3ef592aba5
					
				| @ -5,4 +5,12 @@ class Hour extends Time { | ||||
|   const UNIT = self::UNIT_MINUTES; | ||||
| 
 | ||||
|   const FORMAT = "%hh%M"; | ||||
| 
 | ||||
|   function format(?string $format=null): string { | ||||
|     $string = parent::format($format); | ||||
|     if (substr($string, -3) == "h00") { | ||||
|       $string = substr($string, 0, -2); | ||||
|     } | ||||
|     return $string; | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -3,6 +3,8 @@ namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeInterface; | ||||
| use nulib\exceptions; | ||||
| use nulib\php\types\vbool; | ||||
| use nulib\php\types\vint; | ||||
| 
 | ||||
| /** | ||||
|  * Class Time: une heure allant de 0h à 24h inclus. | ||||
| @ -15,7 +17,10 @@ class Time { | ||||
|   const UNIT_MINUTES = 60; | ||||
|   const UNIT_SECONDS = 1; | ||||
| 
 | ||||
|   const PATTERN = '/^(\d+):(\d+)(?::(\d+))?$/'; | ||||
|   const PATTERNS = [ | ||||
|     '/^(\d+)[:.h](\d+)(?:[:.](\d+))?$/', | ||||
|     '/^(\d+)h(?:(\d+)(?:[:.](\d+))?)?$/' | ||||
|   ]; | ||||
| 
 | ||||
|   /** @var string format par défaut pour l'affichage */ | ||||
|   const FORMAT = "%H:%M:%S"; | ||||
| @ -33,46 +38,59 @@ class Time { | ||||
| 
 | ||||
|   static function isa_time($time): bool { | ||||
|     if ($time === null) return false; | ||||
|     if ($time instanceof Time) return true; | ||||
|     if ($time instanceof self) return true; | ||||
|     if (is_int($time)) return true; | ||||
|     if (is_string($time)) return preg_match(self::PATTERN, $time); | ||||
|     #XXX supporter tous les formats
 | ||||
|     if (is_string($time)) { | ||||
|       foreach (self::PATTERNS as $pattern) { | ||||
|         if (preg_match($pattern, $time)) return true; | ||||
|       } | ||||
|     } | ||||
|     if ($time instanceof DateTimeInterface) return true; | ||||
|     if (is_array($time) && count($time) == 3) return true; | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   static function seconds_now(): int { | ||||
|   protected static function s_now(): int { | ||||
|     $hms = date('His'); | ||||
|     return intval(substr($hms, 0, 2)) * 3600 | ||||
|       + intval(substr($hms, 2, 2)) * 60 | ||||
|       + intval(substr($hms, 4, 2)); | ||||
|   } | ||||
| 
 | ||||
|   static function seconds_get($time, int $unit=self::UNIT_SECONDS): int { | ||||
|     if ($time instanceof self) { | ||||
|   protected static function s_get($time, int $unit=self::UNIT_SECONDS): int { | ||||
|     if ($time === null) { | ||||
|       return 0; | ||||
|     } elseif ($time instanceof self) { | ||||
|       return $time->getSeconds(); | ||||
|     } elseif (is_int($time)) { | ||||
|       return $time * $unit; | ||||
|     } elseif (is_array($time)) { | ||||
|       [$h, $m, $s] = $time; | ||||
|       return $h * 3600 + $m * 60 + $s; | ||||
|     } elseif (is_string($time) && preg_match(self::PATTERN, $time, $ms)) { | ||||
|       $h = $ms[1]; | ||||
|       $m = $ms[2]; | ||||
|       $s = $ms[3] ?? 0; | ||||
|       return intval($h) * 3600 + intval($m) * 60 + intval($s); | ||||
|     } elseif (is_string($time)) { | ||||
|       $matched = false; | ||||
|       foreach (self::PATTERNS as $pattern) { | ||||
|         if (preg_match($pattern, $time, $ms)) { | ||||
|           $matched = true; | ||||
|           break; | ||||
|         } | ||||
|       } | ||||
|       if ($matched) { | ||||
|         $h = $ms[1]; | ||||
|         $m = $ms[2] ?? 0; | ||||
|         $s = $ms[3] ?? 0; | ||||
|         return intval($h) * 3600 + intval($m) * 60 + intval($s); | ||||
|       } | ||||
|     } elseif ($time instanceof DateTimeInterface) { | ||||
|       $hms = $time->format('His'); | ||||
|       return intval(substr($hms, 0, 2)) * 3600 | ||||
|         + intval(substr($hms, 2, 2)) * 60 | ||||
|         + intval(substr($hms, 4, 2)); | ||||
|     } elseif ($time === null) { | ||||
|       return 0; | ||||
|     } else { | ||||
|       throw exceptions::invalid_value($time, "time"); | ||||
|     } elseif (is_array($time) && count($time) == 3) { | ||||
|       [$h, $m, $s] = $time; | ||||
|       return $h * 3600 + $m * 60 + $s; | ||||
|     } | ||||
|     throw exceptions::invalid_value($time, "time"); | ||||
|   } | ||||
| 
 | ||||
|   static function seconds_adjust(int &$seconds, int $unit=self::UNIT_SECONDS, ?int $step=null): int { | ||||
|   protected static function s_adjust(int &$seconds, int $unit=self::UNIT_SECONDS, ?int $step=null): int { | ||||
|     if ($step !== null) $unit *= $step; | ||||
|     $adjust = $seconds % $unit; | ||||
|     if ($seconds < 0) $adjust = -$adjust; | ||||
| @ -80,46 +98,49 @@ class Time { | ||||
|     return $seconds; | ||||
|   } | ||||
| 
 | ||||
|   static function seconds_wrap_start(int &$seconds): int { | ||||
|   protected static function s_wrap_start(int &$seconds): int { | ||||
|     while ($seconds < 0) $seconds += 86400; | ||||
|     if ($seconds >= 86400) $seconds %= 86400; | ||||
|     return $seconds; | ||||
|   } | ||||
| 
 | ||||
|   static function seconds_wrap_end(int &$seconds): int { | ||||
|   protected static function s_wrap_end(int &$seconds): int { | ||||
|     while ($seconds < 0) $seconds += 86400; | ||||
|     if ($seconds > 86400) $seconds %= 86400; | ||||
|     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()} | ||||
|    * @var int la valeur de l'unité en secondes, pour le constructeur et les | ||||
|    * méthodes {@link setu()}, {@link addu()} et {@link subu()} | ||||
|    */ | ||||
|   function UNIT(): int { | ||||
|     return static::UNIT; | ||||
|   } const UNIT = self::UNIT_SECONDS; | ||||
|   const UNIT = self::UNIT_SECONDS; | ||||
| 
 | ||||
|   /** | ||||
|    * @return int|null un nombre d'unité dont l'heure doit être multiple. par | ||||
|    * @var int|null un nombre d'unité dont l'heure doit être multiple. par | ||||
|    * exemple, si l'unité est la minute, une valeur 5 permet d'avoir des heures | ||||
|    * qui vont de 5 en 5 minutes (0h00, 0h05, 0h10, etc.) | ||||
|    */ | ||||
|   protected function STEP(): ?int { | ||||
|     return static::STEP; | ||||
|   } const STEP = null; | ||||
|   const STEP = null; | ||||
| 
 | ||||
|   /** @return bool s'il faut garder les heures dans la plage [0, 24h] */ | ||||
|   protected function WRAP(): bool { | ||||
|     return static::WRAP; | ||||
|   } const WRAP = true; | ||||
|   /** @var bool s'il faut garder les heures dans la plage [0, 24h] */ | ||||
|   const WRAP = true; | ||||
| 
 | ||||
|   function __construct($time=null) { | ||||
|     if ($time === null) $seconds = self::seconds_now(); | ||||
|     else $seconds = self::seconds_get($time, $this->UNIT()); | ||||
|   function __construct($time=null, ?array $params=null) { | ||||
|     $this->unit = vint::with($params["unit"] ?? static::UNIT); | ||||
|     $this->step = vint::withn($params["step"] ?? self::STEP); | ||||
|     $this->wrap = vbool::with($params["wrap"] ?? self::WRAP); | ||||
|     if ($time === null) $seconds = self::s_now(); | ||||
|     else $seconds = self::s_get($time, $this->unit); | ||||
|     $this->setSeconds($seconds); | ||||
|   } | ||||
| 
 | ||||
|   protected int $unit; | ||||
| 
 | ||||
|   protected ?int $step; | ||||
| 
 | ||||
|   protected bool $wrap; | ||||
| 
 | ||||
|   protected int $seconds; | ||||
| 
 | ||||
|   function getSeconds(): int { | ||||
| @ -135,13 +156,13 @@ class Time { | ||||
|    * @return int le nombre de seconde effectif, après correction | ||||
|    */ | ||||
|   protected function setSeconds(?int $seconds): int { | ||||
|     $this->seconds = $seconds ?? self::seconds_now(); | ||||
|     $this->seconds = $seconds ?? self::s_now(); | ||||
|     return $this->afterUpdate(); | ||||
|   } | ||||
| 
 | ||||
|   protected function afterUpdate(): int { | ||||
|     self::seconds_adjust($this->seconds, $this->UNIT(), $this->STEP()); | ||||
|     if ($this->WRAP()) $this->wrapEnd(); | ||||
|     self::s_adjust($this->seconds, $this->unit, $this->step); | ||||
|     if ($this->wrap) $this->wrapEnd(); | ||||
|     return $this->seconds; | ||||
|   } | ||||
| 
 | ||||
| @ -150,7 +171,7 @@ class Time { | ||||
|    * propice à l'utilisation comme borne inférieure d'une période | ||||
|    */ | ||||
|   function wrapStart(): self { | ||||
|     self::seconds_wrap_start($this->seconds); | ||||
|     self::s_wrap_start($this->seconds); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
| @ -159,7 +180,7 @@ class Time { | ||||
|    * propice à l'utilisation comme borne supérieure d'une période | ||||
|    */ | ||||
|   function wrapEnd(): self { | ||||
|     self::seconds_wrap_end($this->seconds); | ||||
|     self::s_wrap_end($this->seconds); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
| @ -174,11 +195,13 @@ class Time { | ||||
|       "%H", "%h", | ||||
|       "%M", "%m", | ||||
|       "%S", "%s", | ||||
|       "%%", | ||||
|     ]; | ||||
|     $replaces = [ | ||||
|       sprintf("%02u", $h), strval($h), | ||||
|       sprintf("%02u", $m), strval($m), | ||||
|       sprintf("%02u", $s), strval($s), | ||||
|       "%", | ||||
|     ]; | ||||
|     return str_replace($searches, $replaces, $format); | ||||
|   } | ||||
| @ -189,39 +212,51 @@ class Time { | ||||
| 
 | ||||
|   /** @return int le nombre d'unités */ | ||||
|   function getu(): int { | ||||
|     return intdiv($this->seconds, $this->UNIT()); | ||||
|     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 { | ||||
|     $this->setSeconds($count * $this->UNIT()); | ||||
|   function setu(int $count): self { | ||||
|     $this->setSeconds($count * $this->unit); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   /** créer une nouvelle heure en ajoutant à cette heure le nombre d'unités spécifiées */ | ||||
|   function addu(int $count=1): self { | ||||
|     $this->setSeconds($this->seconds + $count * $this->UNIT()); | ||||
|     $count *= $this->unit; | ||||
|     if ($this->step !== null) $count *= $this->step; | ||||
|     $this->setSeconds($this->seconds + $count); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   /** créer une nouvelle heure en soustrayant à cette heure le nombre d'unités spécifiées */ | ||||
|   function subu(int $count=1): self { | ||||
|     $this->setSeconds($this->seconds - $count * $this->UNIT()); | ||||
|     $count *= $this->unit; | ||||
|     if ($this->step !== null) $count *= $this->step; | ||||
|     $this->setSeconds($this->seconds - $count); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   /** créer une nouvelle heure en ajoutant à cette heure l'heure spécifiée */ | ||||
|   function add(?self $time): self { | ||||
|   /** forcer cette heure à l'heure spécifiée */ | ||||
|   function set($time): self { | ||||
|     if ($time === null) $seconds = self::s_now(); | ||||
|     else $seconds = self::with($time)->getSeconds(); | ||||
|     $this->setSeconds($seconds); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   /** ajouter à cette heure l'heure spécifiée */ | ||||
|   function add($time): self { | ||||
|     if ($time !== null) { | ||||
|       $this->setSeconds($this->seconds + $time->getSeconds()); | ||||
|       $this->setSeconds($this->seconds + self::with($time)->getSeconds()); | ||||
|     } | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   /** créer une nouvelle heure en soustrayant à cette heure l'heure spécifiée */ | ||||
|   function sub(?self $time): self { | ||||
|   /** soustraire à cette heure l'heure spécifiée */ | ||||
|   function sub($time): self { | ||||
|     if ($time !== null) { | ||||
|       $this->setSeconds($this->seconds - $time->getSeconds()); | ||||
|       $this->setSeconds($this->seconds - self::with($time)->getSeconds()); | ||||
|     } | ||||
|     return $this; | ||||
|   } | ||||
| @ -230,24 +265,24 @@ class Time { | ||||
|    * 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 compare(?self $time): int { | ||||
|   function compare($time): int { | ||||
|     if ($time === null) return 1; | ||||
|     else return $this->seconds - $time->getSeconds(); | ||||
|     else return $this->seconds - self::with($time)->getSeconds(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * tester si cette heure est avant ou égale à l'heure spécifiée | ||||
|    */ | ||||
|   function before(?self $other): bool { | ||||
|   function before($other): bool { | ||||
|     if ($other === null) return false; | ||||
|     else return $this->seconds <= $other->getSeconds(); | ||||
|     else return $this->seconds <= self::with($other)->getSeconds(); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * tester si cette heure est après ou égale à l'heure spécifiée | ||||
|    */ | ||||
|   function after(?self $other): bool { | ||||
|   function after($other): bool { | ||||
|     if ($other === null) return true; | ||||
|     else return $this->seconds >= $other->getSeconds(); | ||||
|     else return $this->seconds >= self::with($other)->getSeconds(); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -2,24 +2,59 @@ | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use nulib\tests\TestCase; | ||||
| use nulib\ValueException; | ||||
| 
 | ||||
| class HourTest extends TestCase { | ||||
|   function testParse() { | ||||
|     self::assertSame("8h", strval(new Hour("08:00:00"))); | ||||
|     self::assertSame("8h", strval(new Hour("8:0"))); | ||||
|     self::assertSame("8h", strval(new Hour("8.0"))); | ||||
|     self::assertSame("8h", strval(new Hour("8h"))); | ||||
| 
 | ||||
|     self::assertSame("8h15", strval(new Hour("08:15:00"))); | ||||
|     self::assertSame("8h15", strval(new Hour("8:15"))); | ||||
|     self::assertSame("8h15", strval(new Hour("8.15"))); | ||||
|     self::assertSame("8h15", strval(new Hour("8h15"))); | ||||
| 
 | ||||
|     self::assertSame("8h15", strval(new Hour("08:15:23"))); | ||||
|     self::assertSame("8h15", strval(new Hour("8:15.23"))); | ||||
|     self::assertSame("8h15", strval(new Hour("8.15.23"))); | ||||
|     self::assertSame("8h15", strval(new Hour("8h15.23"))); | ||||
| 
 | ||||
|     self::assertSame("31h11", strval(new Hour("30:70:80", [ | ||||
|       "wrap" => false, | ||||
|     ]))); | ||||
|     self::assertSame("7h11", strval(new Hour("30:70:80"))); | ||||
| 
 | ||||
|     self::assertException(ValueException::class, function() { | ||||
|       return strval(new Hour("bad format")); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function testFormat() { | ||||
|     self::assertSame("0h00", (new Hour(0))->format()); | ||||
|     self::assertSame("0h", (new Hour(0))->format()); | ||||
|     self::assertSame("0h56", (new Hour(56))->format()); | ||||
|     self::assertSame("2h00", (new Hour(120))->format()); | ||||
|     self::assertSame("2h", (new Hour(120))->format()); | ||||
|     self::assertSame("23h59", (new Hour(1439))->format()); | ||||
|     self::assertSame("24h00", (new Hour(1440))->format()); | ||||
|     self::assertSame("24h", (new Hour(1440))->format()); | ||||
|     self::assertSame("0h01", (new Hour(1441))->format()); | ||||
|   } | ||||
| 
 | ||||
|   function testStep() { | ||||
|     $h = new class extends Hour { | ||||
|       const STEP = 5; | ||||
|     }; | ||||
|     $h->newu(10); self::assertSame("0h10", strval($h)); | ||||
|     $h->newu(12); self::assertSame("0h10", strval($h)); | ||||
|     $h->newu(15); self::assertSame("0h15", strval($h)); | ||||
|     $h->newu(17); self::assertSame("0h15", strval($h)); | ||||
|     $h = new Hour(null, [ | ||||
|       "step" => 5, | ||||
|     ]); | ||||
|     $h->setu(10); self::assertSame("0h10", strval($h)); | ||||
|     $h->setu(12); self::assertSame("0h10", strval($h)); | ||||
|     $h->setu(15); self::assertSame("0h15", strval($h)); | ||||
|     $h->setu(17); self::assertSame("0h15", strval($h)); | ||||
| 
 | ||||
|     $h->set("8h"); | ||||
|     $h->addu(); self::assertSame("8h05", strval($h)); | ||||
|     $h->addu(); self::assertSame("8h10", strval($h)); | ||||
|     $h->addu(); self::assertSame("8h15", strval($h)); | ||||
|     $h->subu(); self::assertSame("8h10", strval($h)); | ||||
|     $h->subu(); self::assertSame("8h05", strval($h)); | ||||
|     $h->subu(); self::assertSame("8h", strval($h)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -2,9 +2,36 @@ | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use nulib\tests\TestCase; | ||||
| use nulib\ValueException; | ||||
| 
 | ||||
| class TimeTest extends TestCase { | ||||
|   function testGetc() { | ||||
|   function testParse() { | ||||
|     self::assertSame("08:00:00", strval(new Time("08:00:00"))); | ||||
|     self::assertSame("08:00:00", strval(new Time("8:0"))); | ||||
|     self::assertSame("08:00:00", strval(new Time("8.0"))); | ||||
|     self::assertSame("08:00:00", strval(new Time("8h"))); | ||||
| 
 | ||||
|     self::assertSame("08:15:00", strval(new Time("08:15:00"))); | ||||
|     self::assertSame("08:15:00", strval(new Time("8:15"))); | ||||
|     self::assertSame("08:15:00", strval(new Time("8.15"))); | ||||
|     self::assertSame("08:15:00", strval(new Time("8h15"))); | ||||
| 
 | ||||
|     self::assertSame("08:15:23", strval(new Time("08:15:23"))); | ||||
|     self::assertSame("08:15:23", strval(new Time("8:15.23"))); | ||||
|     self::assertSame("08:15:23", strval(new Time("8.15.23"))); | ||||
|     self::assertSame("08:15:23", strval(new Time("8h15.23"))); | ||||
| 
 | ||||
|     self::assertSame("31:11:20", strval(new Time("30:70:80", [ | ||||
|       "wrap" => false, | ||||
|     ]))); | ||||
|     self::assertSame("07:11:20", strval(new Time("30:70:80"))); | ||||
| 
 | ||||
|     self::assertException(ValueException::class, function() { | ||||
|       return strval(new Time("bad format")); | ||||
|     }); | ||||
|   } | ||||
| 
 | ||||
|   function testGetu() { | ||||
|     self::assertSame(0, (new Time(0))->getu()); | ||||
|     self::assertSame(86399, (new Time(-1))->getu()); | ||||
|     self::assertSame(1, (new Time(1))->getu()); | ||||
| @ -13,7 +40,7 @@ class TimeTest extends TestCase { | ||||
|     self::assertSame(0, (new Time(-86400))->getu()); | ||||
|   } | ||||
| 
 | ||||
|   function testAddc() { | ||||
|   function testAddu() { | ||||
|     $t = new Time(0); | ||||
|     $t->addu(0); self::assertSame(0, $t->getu()); | ||||
|     $t->addu(10); self::assertSame(10, $t->getu()); | ||||
| @ -24,7 +51,7 @@ class TimeTest extends TestCase { | ||||
|     $t->addu(-86400); self::assertSame(0, $t->getu()); | ||||
|   } | ||||
| 
 | ||||
|   function testSubc() { | ||||
|   function testSubu() { | ||||
|     $t = new Time(0); | ||||
|     $t->subu(-86400); self::assertSame(86400, $t->getu()); | ||||
|     $t->subu(86400); self::assertSame(0, $t->getu()); | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user