diff --git a/php/src/A.php b/php/src/A.php index 75f0284..dffd3d2 100644 --- a/php/src/A.php +++ b/php/src/A.php @@ -218,10 +218,10 @@ class A { static final function filter_f($dest): void { self::filter_if($dest, [cv::class, "f"]);} static final function filter_pt($dest): void { self::filter_if($dest, [cv::class, "pt"]);} static final function filter_pf($dest): void { self::filter_if($dest, [cv::class, "pf"]);} - static final function filter_equals($dest, $value): void { self::filter_if($dest, cv::equals($value)); } - static final function filter_not_equals($dest, $value): void { self::filter_if($dest, cv::not_equals($value)); } - static final function filter_same($dest, $value): void { self::filter_if($dest, cv::same($value)); } - static final function filter_not_same($dest, $value): void { self::filter_if($dest, cv::not_same($value)); } + static final function filter_equals($dest, $value): void { self::filter_if($dest, cv::Fequals($value)); } + static final function filter_not_equals($dest, $value): void { self::filter_if($dest, cv::Fnot_equals($value)); } + static final function filter_same($dest, $value): void { self::filter_if($dest, cv::Fsame($value)); } + static final function filter_not_same($dest, $value): void { self::filter_if($dest, cv::Fnot_same($value)); } ############################################################################# diff --git a/php/src/cl.php b/php/src/cl.php index 2c2bac1..f0919ea 100644 --- a/php/src/cl.php +++ b/php/src/cl.php @@ -817,10 +817,10 @@ class cl { static final function all_f(?array $array): bool { return self::all_if($array, [cv::class, "f"]);} static final function all_pt(?array $array): bool { return self::all_if($array, [cv::class, "pt"]);} static final function all_pf(?array $array): bool { return self::all_if($array, [cv::class, "pf"]);} - static final function all_equals(?array $array, $value): bool { return self::all_if($array, cv::equals($value)); } - static final function all_not_equals(?array $array, $value): bool { return self::all_if($array, cv::not_equals($value)); } - static final function all_same(?array $array, $value): bool { return self::all_if($array, cv::same($value)); } - static final function all_not_same(?array $array, $value): bool { return self::all_if($array, cv::not_same($value)); } + static final function all_equals(?array $array, $value): bool { return self::all_if($array, cv::Fequals($value)); } + static final function all_not_equals(?array $array, $value): bool { return self::all_if($array, cv::Fnot_equals($value)); } + static final function all_same(?array $array, $value): bool { return self::all_if($array, cv::Fsame($value)); } + static final function all_not_same(?array $array, $value): bool { return self::all_if($array, cv::Fnot_same($value)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -842,10 +842,10 @@ class cl { static final function any_f(?array $array): bool { return self::any_if($array, [cv::class, "f"]);} static final function any_pt(?array $array): bool { return self::any_if($array, [cv::class, "pt"]);} static final function any_pf(?array $array): bool { return self::any_if($array, [cv::class, "pf"]);} - static final function any_equals(?array $array, $value): bool { return self::any_if($array, cv::equals($value)); } - static final function any_not_equals(?array $array, $value): bool { return self::any_if($array, cv::not_equals($value)); } - static final function any_same(?array $array, $value): bool { return self::any_if($array, cv::same($value)); } - static final function any_not_same(?array $array, $value): bool { return self::any_if($array, cv::not_same($value)); } + static final function any_equals(?array $array, $value): bool { return self::any_if($array, cv::Fequals($value)); } + static final function any_not_equals(?array $array, $value): bool { return self::any_if($array, cv::Fnot_equals($value)); } + static final function any_same(?array $array, $value): bool { return self::any_if($array, cv::Fsame($value)); } + static final function any_not_same(?array $array, $value): bool { return self::any_if($array, cv::Fnot_same($value)); } #~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ @@ -876,10 +876,10 @@ class cl { static final function filter_f(?array $array): ?array { return self::filter_if($array, [cv::class, "f"]);} static final function filter_pt(?array $array): ?array { return self::filter_if($array, [cv::class, "pt"]);} static final function filter_pf(?array $array): ?array { return self::filter_if($array, [cv::class, "pf"]);} - static final function filter_equals(?array $array, $value): ?array { return self::filter_if($array, cv::equals($value)); } - static final function filter_not_equals(?array $array, $value): ?array { return self::filter_if($array, cv::not_equals($value)); } - static final function filter_same(?array $array, $value): ?array { return self::filter_if($array, cv::same($value)); } - static final function filter_not_same(?array $array, $value): ?array { return self::filter_if($array, cv::not_same($value)); } + static final function filter_equals(?array $array, $value): ?array { return self::filter_if($array, cv::Fequals($value)); } + static final function filter_not_equals(?array $array, $value): ?array { return self::filter_if($array, cv::Fnot_equals($value)); } + static final function filter_same(?array $array, $value): ?array { return self::filter_if($array, cv::Fsame($value)); } + static final function filter_not_same(?array $array, $value): ?array { return self::filter_if($array, cv::Fnot_same($value)); } ############################################################################# diff --git a/php/src/cv.php b/php/src/cv.php index fd61a8e..ac3dbac 100644 --- a/php/src/cv.php +++ b/php/src/cv.php @@ -49,7 +49,7 @@ class cv { * contruire une fonction qui retourne vrai si on lui passe en argument une * valeur égale à $value */ - static final function equals($value): callable { + static final function Fequals($value): callable { return function ($arg) use($value) { return $arg == $value; }; } @@ -57,7 +57,7 @@ class cv { * contruire une fonction qui retourne vrai si on lui passe en argument une * valeur qui n'est pas égale à $value */ - static final function not_equals($value): callable { + static final function Fnot_equals($value): callable { return function ($arg) use($value) { return $arg != $value; }; } @@ -65,7 +65,7 @@ class cv { * contruire une fonction qui retourne vrai si on lui passe en argument une * valeur strictement égale à $value */ - static final function same($value): callable { + static final function Fsame($value): callable { return function ($arg) use($value) { return $arg === $value; }; } @@ -73,7 +73,7 @@ class cv { * contruire une fonction qui retourne vrai si on lui passe en argument une * valeur qui n'est pas strictement égale à $value */ - static final function not_same($value): callable { + static final function Fnot_same($value): callable { return function ($arg) use($value) { return $arg !== $value; }; } @@ -231,6 +231,24 @@ class cv { ############################################################################# + /** + * tester l'égalité non stricte de deux valeurs, dans le cas où leurs types ne + * sont pas forcément cohérents: par exemple eq("1", 1) === true + * + * cette fonction est utile par exemple quand on veut comparer des données + * provenant d'une base de données: PHP a la facheuse tendance de retourner + * les nombres sous forme de chaines + */ + static final function equals($a, $b): bool { + # cette fonction existe parce que le type des valeurs retournées par la BDD + # n'est pas cohérent, "1" au lieu de 1 par exemple + if ($a === null) return $b === null; + elseif ($b === null) return $a === null; + elseif (is_scalar($a)) return strval($a) === strval($b); + # ne pas utiliser l'égalité stricte ici: ce sont des objets + else return $a == $b; + } + /** retourner -1, 0 ou 1 en fonction de l'ordre relatif entre $a et $b */ static final function compare($a, $b): int { if ($a === $b) return 0; diff --git a/php/src/db/CapacitorStorage.php b/php/src/db/CapacitorStorage.php index 232d935..65aa09c 100644 --- a/php/src/db/CapacitorStorage.php +++ b/php/src/db/CapacitorStorage.php @@ -3,6 +3,7 @@ namespace nulib\db; use nulib\A; use nulib\cl; +use nulib\cv; use nulib\db\_private\_migration; use nulib\php\func; use nulib\ValueException; @@ -479,8 +480,9 @@ abstract class CapacitorStorage { # ne jamais mettre à jour la clé primaire continue; } - $pvalue = $praw[$col] ?? null; - if ($value !== $pvalue) $updates[$col] = $value; + if (!cv::equals($value, $praw[$col] ?? null)) { + $updates[$col] = $value; + } } if (count($updates) == 1 && array_key_first($updates) == "modified_") { # si l'unique modification porte sur la date de modification, alors diff --git a/php/src/php/time/DateTime.php b/php/src/php/time/DateTime.php index f819fe2..438b614 100644 --- a/php/src/php/time/DateTime.php +++ b/php/src/php/time/DateTime.php @@ -139,6 +139,12 @@ class DateTime extends \DateTime { return false; } + /** retourner le nombre de secondes depuis minuit */ + static function _nbsecs_format(\DateTime $datetime): string { + [$h, $m, $s] = explode(",", $datetime->format("H,i,s")); + return $h * 3600 + $m * 60 + $s; + } + static function _YmdHMSZ_format(\DateTime $datetime): string { $YmdHMS = $datetime->format("Ymd\\THis"); $Z = $datetime->format("P"); @@ -156,6 +162,7 @@ class DateTime extends \DateTime { "second" => "s", "wday" => "N", "wnum" => "W", + "nbsecs" => [self::class, "_nbsecs_format"], ]; const STRING_FORMATS = [ "timezone" => "P", @@ -166,14 +173,6 @@ class DateTime extends \DateTime { "YmdHMSZ" => [self::class, "_YmdHMSZ_format"], ]; - static function clone(DateTimeInterface $dateTime): self { - if ($dateTime instanceof static) return clone $dateTime; - $clone = new static(); - $clone->setTimestamp($dateTime->getTimestamp()); - $clone->setTimezone($dateTime->getTimezone()); - return $clone; - } - /** * corriger une année à deux chiffres qui est située dans le passé et * retourner l'année à 4 chiffres. @@ -282,7 +281,7 @@ class DateTime extends \DateTime { if ($Y !== null) { if ($H === null) $datetime = sprintf("%04d-%02d-%02d", $Y, $m, $d); else $datetime = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $Y, $m, $d, $H, $M, $S); - if ($Z !== null) $timezone = new DateTimeZone(self::fix_z($Z)); + if ($Z !== null) $timezone ??= new DateTimeZone(self::fix_z($Z)); } parent::__construct($datetime, $timezone); @@ -295,7 +294,7 @@ class DateTime extends \DateTime { } else { $datetime = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $Y, $m, $d, $H ?? 0, $M ?? 0, $S ?? 0); } - if ($Z !== null) $timezone = new DateTimeZone(self::fix_z($Z)); + if ($Z !== null) $timezone ??= new DateTimeZone(self::fix_z($Z)); parent::__construct($datetime, $timezone); } else { @@ -308,6 +307,10 @@ class DateTime extends \DateTime { } } + function clone(): self { + return clone $this; + } + function diff($target, $absolute=false): DateInterval { return new DateInterval(parent::diff($target, $absolute)); } @@ -374,7 +377,7 @@ class DateTime extends \DateTime { function __get($name) { if (array_key_exists($name, self::INT_FORMATS)) { $format = self::INT_FORMATS[$name]; - if (is_callable($format)) return $format($this); + if (is_callable($format)) return intval($format($this)); else return intval($this->format($format)); } elseif (array_key_exists($name, self::STRING_FORMATS)) { $format = self::STRING_FORMATS[$name]; diff --git a/php/src/php/time/Delay.php b/php/src/php/time/Delay.php index 4afcf37..e773efa 100644 --- a/php/src/php/time/Delay.php +++ b/php/src/php/time/Delay.php @@ -40,8 +40,8 @@ class Delay { "s" => [1, 0], ]; - static function compute_dest(int $x, string $u, ?int $y, DateTime $from): array { - $dest = DateTime::clone($from); + static function compute_dest(int $x, string $u, ?int $y, ?DateTimeInterface $from): array { + $dest = DateTime::with($from)->clone(); $yu = null; switch ($u) { case "w": @@ -92,7 +92,7 @@ class Delay { function __construct($delay, ?DateTimeInterface $from=null) { if ($from === null) $from = new DateTime(); if ($delay === "INF") { - $dest = DateTime::clone($from); + $dest = DateTime::with($from)->clone(); $dest->add(new DateInterval("P9999Y")); $repr = "INF"; } elseif (is_int($delay)) { diff --git a/php/tests/php/time/DateTest.php b/php/tests/php/time/DateTest.php index 857ca33..458e42b 100644 --- a/php/tests/php/time/DateTest.php +++ b/php/tests/php/time/DateTest.php @@ -29,7 +29,7 @@ class DateTest extends TestCase { function testClone() { $date = self::dt("now"); - $clone = Date::clone($date); + $clone = $date->clone(); self::assertInstanceOf(DateTime::class, $clone); } diff --git a/php/tests/php/time/DateTimeTest.php b/php/tests/php/time/DateTimeTest.php index 088bc79..67cc9de 100644 --- a/php/tests/php/time/DateTimeTest.php +++ b/php/tests/php/time/DateTimeTest.php @@ -32,13 +32,17 @@ class DateTimeTest extends TestCase { function testDateTimeZ() { $date = new DateTime("20240405T091523Z"); + self::assertSame("20240405T131523", $date->YmdHMS); + self::assertSame("20240405T131523+04:00", $date->YmdHMSZ); + # comme on spécifie la timezone, la valeur Z est ignorée + $date = new DateTime("20240405T091523Z", new DateTimeZone("Indian/Reunion")); self::assertSame("20240405T091523", $date->YmdHMS); - self::assertSame("20240405T091523Z", $date->YmdHMSZ); + self::assertSame("20240405T091523+04:00", $date->YmdHMSZ); } function testClone() { $date = self::dt("now"); - $clone = DateTime::clone($date); + $clone = $date->clone(); self::assertInstanceOf(DateTime::class, $clone); } @@ -51,7 +55,7 @@ class DateTimeTest extends TestCase { self::assertSame("05/04/2024 00:00:00", strval(new DateTime("20240405"))); self::assertSame("05/04/2024 00:00:00", strval(new DateTime("240405"))); self::assertSame("05/04/2024 09:15:23", strval(new DateTime("20240405T091523"))); - self::assertSame("05/04/2024 09:15:23", strval(new DateTime("20240405T091523Z"))); + self::assertSame("05/04/2024 13:15:23", strval(new DateTime("20240405T091523Z"))); self::assertSame("05/04/2024 09:15:23", strval(new DateTime("5/4/2024 9:15:23"))); self::assertSame("05/04/2024 09:15:23", strval(new DateTime("5/4/2024 9.15.23"))); self::assertSame("05/04/2024 09:15:00", strval(new DateTime("5/4/2024 9:15")));