Date et DateTime sont immutable
This commit is contained in:
		
							parent
							
								
									810ead58d6
								
							
						
					
					
						commit
						c748fed388
					
				| @ -1,7 +1,7 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeZone; | ||||
| use DateTimeInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Class Date: une date | ||||
| @ -9,9 +9,14 @@ use DateTimeZone; | ||||
| class Date extends DateTime { | ||||
|   const DEFAULT_FORMAT = "d/m/Y"; | ||||
| 
 | ||||
|   function __construct($datetime="now", DateTimeZone $timezone=null) { | ||||
|     parent::__construct($datetime, $timezone); | ||||
|     $this->setTime(0, 0); | ||||
|   protected function fix(DateTimeInterface $datetime): \DateTimeInterface { | ||||
|     return $datetime->setTime(0, 0); | ||||
|   } | ||||
| 
 | ||||
|   /** @return MutableDate|self */ | ||||
|   function clone(bool $mutable=false): DateTimeInterface { | ||||
|     if ($mutable) return new MutableDate($this); | ||||
|     else return clone $this; | ||||
|   } | ||||
| 
 | ||||
|   function format($format=self::DEFAULT_FORMAT): string { | ||||
|  | ||||
| @ -1,10 +1,10 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeImmutable; | ||||
| use DateTimeInterface; | ||||
| use DateTimeZone; | ||||
| use InvalidArgumentException; | ||||
| use nulib\str; | ||||
| 
 | ||||
| /** | ||||
|  * Class DateTime: une date et une heure | ||||
| @ -24,252 +24,78 @@ use nulib\str; | ||||
|  * @property-read string $YmdHMS | ||||
|  * @property-read string $YmdHMSZ | ||||
|  */ | ||||
| class DateTime extends \DateTime { | ||||
|   static function with($datetime): self { | ||||
|     if ($datetime instanceof static) return $datetime; | ||||
|     else return new static($datetime); | ||||
|   } | ||||
| 
 | ||||
|   static function withn($datetime): ?self { | ||||
|     if ($datetime === null) return null; | ||||
|     elseif ($datetime instanceof static) return $datetime; | ||||
|     else return new static($datetime); | ||||
|   } | ||||
| 
 | ||||
|   static function ensure(&$datetime): void { | ||||
|     $datetime = static::withn($datetime); | ||||
|   } | ||||
| 
 | ||||
|   const DMY_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))?$/'; | ||||
|   const YMD_PATTERN = '/^((?:\d{2})?\d{2})(\d{2})(\d{2})$/'; | ||||
|   const DMYHIS_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))? +(\d+)[h:.](\d+)(?:[:.](\d+))?$/'; | ||||
|   const YMDHISZ_PATTERN = '/^((?:\d{2})?\d{2})-?(\d{2})-?(\d{2})[tT](\d{2}):?(\d{2}):?(\d{2})?([zZ]|\+\d{2}:?\d{2})?$/'; | ||||
| 
 | ||||
| 
 | ||||
|   protected static function get_value(array $datetime, ?string $key, ?string $k, ?int $index) { | ||||
|     $value = null; | ||||
|     if ($value === null && $key !== null) $value = $datetime[$key] ?? null; | ||||
|     if ($value === null && $k !== null) $value = $datetime[$k] ?? null; | ||||
|     if ($value === null && $index !== null) $value = $datetime[$index] ?? null; | ||||
|     return $value; | ||||
|   } | ||||
| 
 | ||||
|   private static function parse_int(array $datetime, ?string $key, ?string $k, ?int $index, ?int &$part, bool $required=true, ?int $default=null): bool { | ||||
|     $part = null; | ||||
|     $value = self::get_value($datetime, $key, $k, $index); | ||||
|     if ($value === null) { | ||||
|       if ($required && $default === null) return false; | ||||
|       $part = $default; | ||||
|       return true; | ||||
|     } | ||||
|     if (is_numeric($value)) { | ||||
|       $part = intval($value); | ||||
|       return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   private static function parse_str(array $datetime, ?string $key, ?string $k, ?int $index, ?string &$part, bool $required = true, ?string $default=null): bool { | ||||
|     $part = null; | ||||
|     $value = self::get_value($datetime, $key, $k, $index); | ||||
|     if ($value === null) { | ||||
|       if ($required && $default === null) return false; | ||||
|       $part = $default; | ||||
|       return true; | ||||
|     } | ||||
|     if (is_string($value)) { | ||||
|       $part = $value; | ||||
|       return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   protected static function parse_array(array $datetime): ?array { | ||||
|     if (!self::parse_int($datetime, "year", "Y", 0, $year)) return null; | ||||
|     if (!self::parse_int($datetime, "month", "m", 1, $month)) return null; | ||||
|     if (!self::parse_int($datetime, "day", "d", 2, $day)) return null; | ||||
|     self::parse_int($datetime, "hour", "H", 3, $hour, false); | ||||
|     self::parse_int($datetime, "minute", "M", 4, $minute, false); | ||||
|     self::parse_int($datetime, "second", "S", 5, $second, false); | ||||
|     self::parse_str($datetime, "tz", null, 6, $tz, false); | ||||
|     return [$year, $month, $day, $hour, $minute, $second, $tz]; | ||||
|   } | ||||
| 
 | ||||
|   static function isa($datetime): bool { | ||||
|     if ($datetime === null) return false; | ||||
|     if ($datetime instanceof DateTimeInterface) return true; | ||||
|     if (is_int($datetime)) return true; | ||||
|     if (is_string($datetime)) { | ||||
|       return preg_match(self::DMY_PATTERN, $datetime) || | ||||
|         preg_match(self::YMD_PATTERN, $datetime) || | ||||
|         preg_match(self::DMYHIS_PATTERN, $datetime) || | ||||
|         preg_match(self::YMDHISZ_PATTERN, $datetime); | ||||
|     } | ||||
|     if (is_array($datetime)) { | ||||
|       return self::parse_array($datetime) !== null; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   static function isa_datetime($datetime, bool $frOnly=false): bool { | ||||
|     if ($datetime === null) return false; | ||||
|     if ($datetime instanceof DateTimeInterface) return true; | ||||
|     if (is_int($datetime)) return true; | ||||
|     if (is_string($datetime)) { | ||||
|       return preg_match(self::DMYHIS_PATTERN, $datetime) || | ||||
|         (!$frOnly && preg_match(self::YMDHISZ_PATTERN, $datetime)); | ||||
|     } | ||||
|     if (is_array($datetime)) { | ||||
|       return self::parse_array($datetime) !== null; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   static function isa_date($date, bool $frOnly=false): bool { | ||||
|     if ($date === null) return false; | ||||
|     if ($date instanceof DateTimeInterface) return true; | ||||
|     if (is_int($date)) return true; | ||||
|     if (is_string($date)) { | ||||
|       return preg_match(self::DMY_PATTERN, $date) || | ||||
|         (!$frOnly && preg_match(self::YMD_PATTERN, $date)); | ||||
|     } | ||||
|     if (is_array($date)) { | ||||
|       return self::parse_array($date) !== null; | ||||
|     } | ||||
|     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"); | ||||
|     if ($Z === "+00:00") $Z = "Z"; | ||||
|     return "$YmdHMS$Z"; | ||||
|   } | ||||
| class DateTime extends \DateTimeImmutable { | ||||
|   use _TDateTime; | ||||
| 
 | ||||
|   const DEFAULT_FORMAT = "d/m/Y H:i:s"; | ||||
|   const INT_FORMATS = [ | ||||
|     "year" => "Y", | ||||
|     "month" => "m", | ||||
|     "day" => "d", | ||||
|     "hour" => "H", | ||||
|     "minute" => "i", | ||||
|     "second" => "s", | ||||
|     "wday" => "N", | ||||
|     "wnum" => "W", | ||||
|     "nbsecs" => [self::class, "_nbsecs_format"], | ||||
|   ]; | ||||
|   const STRING_FORMATS = [ | ||||
|     "timezone" => "P", | ||||
|     "datetime" => "d/m/Y H:i:s", | ||||
|     "date" => "d/m/Y", | ||||
|     "Ymd" => "Ymd", | ||||
|     "YmdHMS" => "Ymd\\THis", | ||||
|     "YmdHMSZ" => [self::class, "_YmdHMSZ_format"], | ||||
|   ]; | ||||
| 
 | ||||
|   /** | ||||
|    * corriger une année à deux chiffres qui est située dans le passé et | ||||
|    * retourner l'année à 4 chiffres. | ||||
|    * $datetime est une spécification de date, avec ou sans fuseau horaire | ||||
|    * | ||||
|    * par exemple, si l'année courante est 2019, alors: | ||||
|    * - fix_past_year('18') === '2018' | ||||
|    * - fix_past_year('19') === '1919' | ||||
|    * - fix_past_year('20') === '1920' | ||||
|    */ | ||||
|   static function fix_past_year(int $year): int { | ||||
|     if ($year < 100) { | ||||
|       $y = getdate(); $y = $y["year"]; | ||||
|       $r = $y % 100; | ||||
|       $c = $y - $r; | ||||
|       if ($year >= $r) $year += $c - 100; | ||||
|       else $year += $c; | ||||
|     } | ||||
|     return $year; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * corriger une année à deux chiffres et retourner l'année à 4 chiffres. | ||||
|    * l'année charnière entre année passée et année future est 70 | ||||
|    * si $datetime ne contient pas de fuseau horaire, elle est réputée être dans | ||||
|    * le fuseau $timezone, qui est le fuseau local par défaut | ||||
|    * | ||||
|    * par exemple, si l'année courante est 2019, alors: | ||||
|    * - fix_past_year('18') === '2018' | ||||
|    * - fix_past_year('19') === '2019' | ||||
|    * - fix_past_year('20') === '2020' | ||||
|    * - fix_past_year('69') === '2069' | ||||
|    * - fix_past_year('70') === '1970' | ||||
|    * - fix_past_year('71') === '1971' | ||||
|    * si $datetime contient un fuseau horaire et si $forceTimezone est vrai, | ||||
|    * alors $datetime est réexprimée dans le fuseau $timezone. | ||||
|    * si $timezone est null alors $forceTimezone vaut vrai par défaut. | ||||
|    * | ||||
|    * datetime         | timezone | forceTimezone | résultat | ||||
|    * -----------------|----------|---------------|--------- | ||||
|    * datetime         | any      | any           | datetime+localtz | ||||
|    * datetime+origtz  | null     | null          | datetime+localtz | ||||
|    * datetime+origtz  | null     | true          | datetime+localtz | ||||
|    * datetime+origtz  | null     | false         | datetime+origtz | ||||
|    * datetime+origtz  | newtz    | null          | datetime+origtz | ||||
|    * datetime+origtz  | newtz    | false         | datetime+origtz | ||||
|    * datetime+origtz  | newtz    | true          | datetime+newtz | ||||
|    */ | ||||
|   static function fix_any_year(int $year): int { | ||||
|     if ($year < 100) { | ||||
|       $y = intval(date("Y")); | ||||
|       $r = $y % 100; | ||||
|       $c = $y - $r; | ||||
|       if ($year >= 70) $year += $c - 100; | ||||
|       else $year += $c; | ||||
|     } | ||||
|     return $year; | ||||
|   } | ||||
| 
 | ||||
|   static function fix_z(?string $Z): ?string { | ||||
|     $Z = strtoupper($Z); | ||||
|     str::del_prefix($Z, "+"); | ||||
|     if (preg_match('/^\d{4}$/', $Z)) { | ||||
|       $Z = substr($Z, 0, 2).":".substr($Z, 2); | ||||
|     } | ||||
|     if ($Z === "Z" || $Z === "UTC" || $Z === "00:00") return "UTC"; | ||||
|     return "GMT+$Z"; | ||||
|   } | ||||
| 
 | ||||
|   function __construct($datetime="now", DateTimeZone $timezone=null, ?bool $forceLocalTimezone=null) { | ||||
|     $forceLocalTimezone ??= $timezone === null; | ||||
|     if ($forceLocalTimezone) { | ||||
|       $setTimezone = $timezone; | ||||
|   function __construct($datetime=null, DateTimeZone $timezone=null, ?bool $forceTimezone=null) { | ||||
|     $resetTimezone = null; | ||||
|     $forceTimezone ??= $timezone === null; | ||||
|     if ($forceTimezone) { | ||||
|       $resetTimezone = $timezone ?? new DateTimeZone(date_default_timezone_get()); | ||||
|       $timezone = null; | ||||
|     } | ||||
| 
 | ||||
|     $datetime ??= "now"; | ||||
|     if ($datetime instanceof \DateTimeInterface) { | ||||
|       $timezone ??= $datetime->getTimezone(); | ||||
|       parent::__construct(); | ||||
|       $this->setTimestamp($datetime->getTimestamp()); | ||||
|       $this->setTimezone($timezone); | ||||
|     if ($datetime instanceof DateTimeImmutable) { | ||||
|       $datetime = \DateTime::createFromImmutable($datetime); | ||||
|     } elseif ($datetime instanceof \DateTime) { | ||||
|       $datetime = clone $datetime; | ||||
|       #XXX sous PHP 8, remplacer les deux commandes ci-dessus par
 | ||||
|       # DateTime::createFromInterface
 | ||||
| 
 | ||||
|     } elseif (is_int($datetime)) { | ||||
|       parent::__construct("now", $timezone); | ||||
|       $this->setTimestamp($datetime); | ||||
|       $timestamp = $datetime; | ||||
|       $datetime = new \DateTime("now", $timezone); | ||||
|       $datetime->setTimestamp($timestamp); | ||||
| 
 | ||||
|     } elseif (is_string($datetime)) { | ||||
|       $Y = $H = $Z = null; | ||||
|       if (preg_match(self::DMY_PATTERN, $datetime, $ms)) { | ||||
|       if (preg_match(_utils::DMY_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[3] ?? null; | ||||
|         if ($Y !== null) $Y = self::fix_any_year(intval($Y)); | ||||
|         if ($Y !== null) $Y = _utils::fix_any_year(intval($Y)); | ||||
|         else $Y = intval(date("Y")); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[1]); | ||||
|       } elseif (preg_match(self::YMD_PATTERN, $datetime, $ms)) { | ||||
|       } elseif (preg_match(_utils::YMD_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[1]; | ||||
|         if (strlen($Y) == 2) $Y = self::fix_any_year(intval($ms[1])); | ||||
|         if (strlen($Y) == 2) $Y = _utils::fix_any_year(intval($ms[1])); | ||||
|         else $Y = intval($Y); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[3]); | ||||
|       } elseif (preg_match(self::DMYHIS_PATTERN, $datetime, $ms)) { | ||||
|       } elseif (preg_match(_utils::DMYHIS_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[3]; | ||||
|         if ($Y !== null) $Y = self::fix_any_year(intval($Y)); | ||||
|         if ($Y !== null) $Y = _utils::fix_any_year(intval($Y)); | ||||
|         else $Y = intval(date("Y")); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[1]); | ||||
|         $H = intval($ms[4]); | ||||
|         $M = intval($ms[5]); | ||||
|         $S = intval($ms[6] ?? 0); | ||||
|       } elseif (preg_match(self::YMDHISZ_PATTERN, $datetime, $ms)) { | ||||
|       } elseif (preg_match(_utils::YMDHISZ_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[1]; | ||||
|         if (strlen($Y) == 2) $Y = self::fix_any_year(intval($ms[1])); | ||||
|         if (strlen($Y) == 2) $Y = _utils::fix_any_year(intval($ms[1])); | ||||
|         else $Y = intval($Y); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[3]); | ||||
| @ -281,73 +107,61 @@ 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(_utils::fix_z($Z)); | ||||
|       } | ||||
|       parent::__construct($datetime, $timezone); | ||||
|       $datetime = new \DateTime($datetime, $timezone); | ||||
| 
 | ||||
|     } elseif (is_array($datetime) && ($datetime = self::parse_array($datetime)) !== null) { | ||||
|       $setTimezone = $timezone; | ||||
|       $timezone = null; | ||||
|     } elseif (is_array($datetime) && ($datetime = _utils::parse_array($datetime)) !== null) { | ||||
|       [$Y, $m, $d, $H, $M, $S, $Z] = $datetime; | ||||
|       if ($H === null && $M === null && $S === null) { | ||||
|         $datetime = sprintf("%04d-%02d-%02d", $Y, $m, $d); | ||||
|       } 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)); | ||||
|       parent::__construct($datetime, $timezone); | ||||
|       if ($Z !== null) $timezone = new DateTimeZone(_utils::fix_z($Z)); | ||||
|       $datetime = new \DateTime($datetime, $timezone); | ||||
|     } | ||||
| 
 | ||||
|     } else { | ||||
|     if ($datetime instanceof DateTimeInterface) { | ||||
|       if ($resetTimezone !== null) $datetime->setTimezone($resetTimezone); | ||||
|       $datetime = $this->fix($datetime); | ||||
|       parent::__construct($datetime->format("Y-m-d\\TH:i:s.uP")); | ||||
|     }  else { | ||||
|       throw new InvalidArgumentException("datetime must be a string or an instance of DateTimeInterface"); | ||||
|     } | ||||
| 
 | ||||
|     if ($forceLocalTimezone) { | ||||
|       $setTimezone ??= new DateTimeZone(date_default_timezone_get()); | ||||
|       $this->setTimezone($setTimezone); | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   function clone(): self { | ||||
|     return clone $this; | ||||
|   protected function fix(DateTimeInterface $datetime): DateTimeInterface { | ||||
|     return $datetime; | ||||
|   } | ||||
| 
 | ||||
|   function diff($target, $absolute=false): DateInterval { | ||||
|     return new DateInterval(parent::diff($target, $absolute)); | ||||
|   } | ||||
| 
 | ||||
|   function format($format=self::DEFAULT_FORMAT): string { | ||||
|     if (array_key_exists($format, self::INT_FORMATS)) { | ||||
|       $format = self::INT_FORMATS[$format]; | ||||
|     } elseif (array_key_exists($format, self::STRING_FORMATS)) { | ||||
|       $format = self::STRING_FORMATS[$format]; | ||||
|     } | ||||
|     if (is_callable($format)) return $format($this); | ||||
|     else return \DateTime::format($format); | ||||
|   /** @return MutableDateTime|self */ | ||||
|   function clone(bool $mutable=false): DateTimeInterface { | ||||
|     if ($mutable) return new MutableDateTime($this); | ||||
|     else return clone $this; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * modifier cet objet pour que l'heure soit à 00:00:00 ce qui le rend propice | ||||
|    * à l'utilisation comme borne inférieure d'une période | ||||
|    */ | ||||
|   function wrapStartOfDay(): self { | ||||
|     $this->setTime(0, 0); | ||||
|     return $this; | ||||
|   function getStartOfDay(): self { | ||||
|     return new static($this->setTime(0, 0)); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * modifier cet objet pour que l'heure soit à 23:59:59.999999 ce qui le rend | ||||
|    * propice à l'utilisation comme borne supérieure d'une période | ||||
|    */ | ||||
|   function wrapEndOfDay(): self { | ||||
|     $this->setTime(23, 59, 59, 999999); | ||||
|     return $this; | ||||
|   function getEndOfDay(): self { | ||||
|     return new static($this->setTime(23, 59, 59, 999999)); | ||||
|   } | ||||
| 
 | ||||
|   function getPrevDay(int $nbDays=1, bool $skipWeekend=false): self { | ||||
|     if ($nbDays == 1 && $skipWeekend && $this->wday == 1) { | ||||
|       $nbdays = 3; | ||||
|       $nbDays = 3; | ||||
|     } | ||||
|     return static::with($this->sub(new \DateInterval("P${nbDays}D"))); | ||||
|     return new static($this->sub(new \DateInterval("P${nbDays}D"))); | ||||
|   } | ||||
| 
 | ||||
|   function getNextDay(int $nbDays=1, bool $skipWeekend=false): self { | ||||
| @ -355,35 +169,6 @@ class DateTime extends \DateTime { | ||||
|       $wday = $this->wday; | ||||
|       if ($wday > 5) $nbDays = 8 - $this->wday; | ||||
|     } | ||||
|     return static::with($this->add(new \DateInterval("P${nbDays}D"))); | ||||
|   } | ||||
| 
 | ||||
|   function getElapsedAt(?DateTime $now=null, ?int $resolution=null): string { | ||||
|     return Elapsed::format_at($this, $now, $resolution); | ||||
|   } | ||||
| 
 | ||||
|   function getElapsedSince(?DateTime $now=null, ?int $resolution=null): string { | ||||
|     return Elapsed::format_since($this, $now, $resolution); | ||||
|   } | ||||
| 
 | ||||
|   function getElapsedDelay(?DateTime $now=null, ?int $resolution=null): string { | ||||
|     return Elapsed::format_delay($this, $now, $resolution); | ||||
|   } | ||||
| 
 | ||||
|   function __toString(): string { | ||||
|     return $this->format(); | ||||
|   } | ||||
| 
 | ||||
|   function __get($name) { | ||||
|     if (array_key_exists($name, self::INT_FORMATS)) { | ||||
|       $format = self::INT_FORMATS[$name]; | ||||
|       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]; | ||||
|       if (is_callable($format)) return $format($this); | ||||
|       else return $this->format($format); | ||||
|     } | ||||
|     throw new InvalidArgumentException("Unknown property $name"); | ||||
|     return new static($this->add(new \DateInterval("P${nbDays}D"))); | ||||
|   } | ||||
| } | ||||
|  | ||||
| @ -39,8 +39,7 @@ class Delay { | ||||
|     "s" => [1, 0], | ||||
|   ]; | ||||
| 
 | ||||
|   static function compute_dest(int $x, string $u, ?int $y, ?DateTimeInterface $from): array { | ||||
|     $dest = DateTime::with($from)->clone(); | ||||
|   protected static function compute_dest(int $x, string $u, ?int $y, MutableDateTime $dest): array { | ||||
|     $yu = null; | ||||
|     switch ($u) { | ||||
|     case "w": | ||||
| @ -89,9 +88,9 @@ class Delay { | ||||
|   } | ||||
| 
 | ||||
|   function __construct($delay, ?DateTimeInterface $from=null) { | ||||
|     if ($from === null) $from = new DateTime(); | ||||
|     $from = MutableDateTime::with($from)->clone(true); | ||||
|     if ($delay === "INF") { | ||||
|       $dest = DateTime::with($from)->clone(); | ||||
|       $dest = $from; | ||||
|       $dest->add(new DateInterval("P9999Y")); | ||||
|       $repr = "INF"; | ||||
|     } elseif (is_int($delay)) { | ||||
| @ -126,11 +125,11 @@ class Delay { | ||||
|     [$this->dest, $this->repr] = $data; | ||||
|   } | ||||
| 
 | ||||
|   /** @var DateTime */ | ||||
|   /** @var MutableDateTime */ | ||||
|   protected $dest; | ||||
| 
 | ||||
|   function getDest(): DateTime { | ||||
|     return $this->dest; | ||||
|     return $this->dest->clone(); | ||||
|   } | ||||
| 
 | ||||
|   function addDuration($duration) { | ||||
| @ -157,7 +156,7 @@ class Delay { | ||||
|   } | ||||
| 
 | ||||
|   protected function _getDiff(?DateTimeInterface $now=null): \DateInterval { | ||||
|     if ($now === null) $now = new DateTime(); | ||||
|     $now ??= new \DateTime(); | ||||
|     return $this->dest->diff($now); | ||||
|   } | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,8 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeInterface; | ||||
| 
 | ||||
| /** | ||||
|  * Class Elapsed: durée entre deux événements | ||||
|  */ | ||||
| @ -124,19 +126,19 @@ class Elapsed { | ||||
|     return self::format_generic($prefix, $d, 0, 0); | ||||
|   } | ||||
|    | ||||
|   static function format_at(DateTime $start, ?DateTime $now=null, ?int $resolution=null): string { | ||||
|   static function format_at(DateTimeInterface $start, ?DateTimeInterface $now=null, ?int $resolution=null): string { | ||||
|     $now ??= new DateTime(); | ||||
|     $seconds = $now->getTimestamp() - $start->getTimestamp(); | ||||
|     return (new self($seconds, $resolution))->formatAt(); | ||||
|   } | ||||
|    | ||||
|   static function format_since(DateTime $start, ?DateTime $now=null, ?int $resolution=null): string { | ||||
|   static function format_since(DateTimeInterface $start, ?DateTimeInterface $now=null, ?int $resolution=null): string { | ||||
|     $now ??= new DateTime(); | ||||
|     $seconds = $now->getTimestamp() - $start->getTimestamp(); | ||||
|     return (new self($seconds, $resolution))->formatSince(); | ||||
|   } | ||||
|    | ||||
|   static function format_delay(DateTime $start, ?DateTime $now=null, ?int $resolution=null): string { | ||||
|   static function format_delay(DateTimeInterface $start, ?DateTimeInterface $now=null, ?int $resolution=null): string { | ||||
|     $now ??= new DateTime(); | ||||
|     $seconds = $now->getTimestamp() - $start->getTimestamp(); | ||||
|     return (new self($seconds, $resolution))->formatDelay(); | ||||
|  | ||||
							
								
								
									
										24
									
								
								php/src/php/time/MutableDate.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										24
									
								
								php/src/php/time/MutableDate.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,24 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeInterface; | ||||
| use DateTimeZone; | ||||
| 
 | ||||
| class MutableDate extends MutableDateTime { | ||||
|   const DEFAULT_FORMAT = "d/m/Y"; | ||||
| 
 | ||||
|   function __construct($datetime="now", DateTimeZone $timezone=null) { | ||||
|     parent::__construct($datetime, $timezone); | ||||
|     $this->setTime(0, 0); | ||||
|   } | ||||
| 
 | ||||
|   /** @return Date|self */ | ||||
|   function clone(bool $mutable=false): DateTimeInterface { | ||||
|     if ($mutable) return clone $this; | ||||
|     else return new Date($this); | ||||
|   } | ||||
| 
 | ||||
|   function format($format=self::DEFAULT_FORMAT): string { | ||||
|     return parent::format($format); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										168
									
								
								php/src/php/time/MutableDateTime.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										168
									
								
								php/src/php/time/MutableDateTime.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,168 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeInterface; | ||||
| use DateTimeZone; | ||||
| use InvalidArgumentException; | ||||
| 
 | ||||
| /** | ||||
|  * Class DateTime: une date et une heure mutables | ||||
|  * | ||||
|  * @property-read int $year | ||||
|  * @property-read int $month | ||||
|  * @property-read int $day | ||||
|  * @property-read int $hour | ||||
|  * @property-read int $minute | ||||
|  * @property-read int $second | ||||
|  * @property-read int $wday | ||||
|  * @property-read int $wnum | ||||
|  * @property-read string $timezone | ||||
|  * @property-read string $datetime | ||||
|  * @property-read string $date | ||||
|  * @property-read string $Ymd | ||||
|  * @property-read string $YmdHMS | ||||
|  * @property-read string $YmdHMSZ | ||||
|  */ | ||||
| class MutableDateTime extends \DateTime { | ||||
|   use _TDateTime; | ||||
| 
 | ||||
|   const DEFAULT_FORMAT = "d/m/Y H:i:s"; | ||||
| 
 | ||||
|   /** | ||||
|    * $datetime est une spécification de date, avec ou sans fuseau horaire | ||||
|    * | ||||
|    * si $datetime ne contient pas de fuseau horaire, elle est réputée être dans | ||||
|    * le fuseau $timezone, qui est le fuseau local par défaut | ||||
|    * | ||||
|    * si $datetime contient un fuseau horaire et si $forceTimezone est vrai, | ||||
|    * alors $datetime est réexprimée dans le fuseau $timezone. | ||||
|    * si $timezone est null alors $forceTimezone vaut vrai par défaut. | ||||
|    * | ||||
|    * datetime         | timezone | forceTimezone | résultat | ||||
|    * -----------------|----------|---------------|--------- | ||||
|    * datetime         | any      | any           | datetime+localtz | ||||
|    * datetime+origtz  | null     | null          | datetime+localtz | ||||
|    * datetime+origtz  | null     | true          | datetime+localtz | ||||
|    * datetime+origtz  | null     | false         | datetime+origtz | ||||
|    * datetime+origtz  | newtz    | null          | datetime+origtz | ||||
|    * datetime+origtz  | newtz    | false         | datetime+origtz | ||||
|    * datetime+origtz  | newtz    | true          | datetime+newtz | ||||
|    */ | ||||
|   function __construct($datetime=null, DateTimeZone $timezone=null, ?bool $forceTimezone=null) { | ||||
|     $resetTimezone = null; | ||||
|     $forceTimezone ??= $timezone === null; | ||||
|     if ($forceTimezone) { | ||||
|       $resetTimezone = $timezone ?? new DateTimeZone(date_default_timezone_get()); | ||||
|       $timezone = null; | ||||
|     } | ||||
| 
 | ||||
|     $datetime ??= "now"; | ||||
|     if ($datetime instanceof \DateTimeInterface) { | ||||
|       $timezone ??= $datetime->getTimezone(); | ||||
|       parent::__construct(); | ||||
|       $this->setTimestamp($datetime->getTimestamp()); | ||||
|       $this->setTimezone($timezone); | ||||
| 
 | ||||
|     } elseif (is_int($datetime)) { | ||||
|       parent::__construct("now", $timezone); | ||||
|       $this->setTimestamp($datetime); | ||||
| 
 | ||||
|     } elseif (is_string($datetime)) { | ||||
|       $Y = $H = $Z = null; | ||||
|       if (preg_match(_utils::DMY_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[3] ?? null; | ||||
|         if ($Y !== null) $Y = _utils::fix_any_year(intval($Y)); | ||||
|         else $Y = intval(date("Y")); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[1]); | ||||
|       } elseif (preg_match(_utils::YMD_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[1]; | ||||
|         if (strlen($Y) == 2) $Y = _utils::fix_any_year(intval($ms[1])); | ||||
|         else $Y = intval($Y); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[3]); | ||||
|       } elseif (preg_match(_utils::DMYHIS_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[3]; | ||||
|         if ($Y !== null) $Y = _utils::fix_any_year(intval($Y)); | ||||
|         else $Y = intval(date("Y")); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[1]); | ||||
|         $H = intval($ms[4]); | ||||
|         $M = intval($ms[5]); | ||||
|         $S = intval($ms[6] ?? 0); | ||||
|       } elseif (preg_match(_utils::YMDHISZ_PATTERN, $datetime, $ms)) { | ||||
|         $Y = $ms[1]; | ||||
|         if (strlen($Y) == 2) $Y = _utils::fix_any_year(intval($ms[1])); | ||||
|         else $Y = intval($Y); | ||||
|         $m = intval($ms[2]); | ||||
|         $d = intval($ms[3]); | ||||
|         $H = intval($ms[4]); | ||||
|         $M = intval($ms[5]); | ||||
|         $S = intval($ms[6] ?? 0); | ||||
|         $Z = $ms[7] ?? null; | ||||
|       } | ||||
|       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(_utils::fix_z($Z)); | ||||
|       } | ||||
|       parent::__construct($datetime, $timezone); | ||||
| 
 | ||||
|     } elseif (is_array($datetime) && ($datetime = _utils::parse_array($datetime)) !== null) { | ||||
|       [$Y, $m, $d, $H, $M, $S, $Z] = $datetime; | ||||
|       if ($H === null && $M === null && $S === null) { | ||||
|         $datetime = sprintf("%04d-%02d-%02d", $Y, $m, $d); | ||||
|       } else { | ||||
|         $datetime = sprintf("%04d-%02d-%02d %02d:%02d:%02d", $Y, $m, $d, $H ?? 0, $M ?? 0, $S ?? 0); | ||||
|       } | ||||
|       if ($Z !== null) $timezone = new DateTimeZone(_utils::fix_z($Z)); | ||||
|       parent::__construct($datetime, $timezone); | ||||
| 
 | ||||
|     } else { | ||||
|       throw new InvalidArgumentException("datetime must be a string or an instance of DateTimeInterface"); | ||||
|     } | ||||
| 
 | ||||
|     if ($resetTimezone !== null) $this->setTimezone($resetTimezone); | ||||
|   } | ||||
| 
 | ||||
|   /** @return DateTime|self */ | ||||
|   function clone(bool $mutable=false): DateTimeInterface { | ||||
|     if ($mutable) return clone $this; | ||||
|     else return new DateTime($this); | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * modifier cet objet pour que l'heure soit à 00:00:00 ce qui le rend propice | ||||
|    * à l'utilisation comme borne inférieure d'une période | ||||
|    */ | ||||
|   function setStartOfDay(): self { | ||||
|     $this->setTime(0, 0); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * modifier cet objet pour que l'heure soit à 23:59:59.999999 ce qui le rend | ||||
|    * propice à l'utilisation comme borne supérieure d'une période | ||||
|    */ | ||||
|   function setEndOfDay(): self { | ||||
|     $this->setTime(23, 59, 59, 999999); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   function setPrevDay(int $nbDays=1, bool $skipWeekend=false): self { | ||||
|     if ($nbDays == 1 && $skipWeekend && $this->wday == 1) { | ||||
|       $nbDays = 3; | ||||
|     } | ||||
|     $this->sub(new \DateInterval("P${nbDays}D")); | ||||
|     return $this; | ||||
|   } | ||||
| 
 | ||||
|   function setNextDay(int $nbDays=1, bool $skipWeekend=false): self { | ||||
|     if ($nbDays == 1 && $skipWeekend) { | ||||
|       $wday = $this->wday; | ||||
|       if ($wday > 5) $nbDays = 8 - $this->wday; | ||||
|     } | ||||
|     $this->add(new \DateInterval("P${nbDays}D")); | ||||
|     return $this; | ||||
|   } | ||||
| } | ||||
							
								
								
									
										103
									
								
								php/src/php/time/_TDateTime.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										103
									
								
								php/src/php/time/_TDateTime.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,103 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeInterface; | ||||
| use InvalidArgumentException; | ||||
| 
 | ||||
| trait _TDateTime { | ||||
|   static function with($datetime): self { | ||||
|     if ($datetime instanceof static) return $datetime; | ||||
|     else return new static($datetime); | ||||
|   } | ||||
| 
 | ||||
|   static function withn($datetime): ?self { | ||||
|     if ($datetime === null) return null; | ||||
|     elseif ($datetime instanceof static) return $datetime; | ||||
|     else return new static($datetime); | ||||
|   } | ||||
| 
 | ||||
|   static function ensure(&$datetime): void { | ||||
|     $datetime = static::withn($datetime); | ||||
|   } | ||||
| 
 | ||||
|   static function isa($datetime): bool { | ||||
|     if ($datetime === null) return false; | ||||
|     if ($datetime instanceof DateTimeInterface) return true; | ||||
|     if (is_int($datetime)) return true; | ||||
|     if (is_string($datetime)) { | ||||
|       return preg_match(_utils::DMY_PATTERN, $datetime) || | ||||
|         preg_match(_utils::YMD_PATTERN, $datetime) || | ||||
|         preg_match(_utils::DMYHIS_PATTERN, $datetime) || | ||||
|         preg_match(_utils::YMDHISZ_PATTERN, $datetime); | ||||
|     } | ||||
|     if (is_array($datetime)) return _utils::parse_array($datetime) !== null; | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   static function isa_datetime($datetime, bool $frOnly=false): bool { | ||||
|     if ($datetime === null) return false; | ||||
|     if ($datetime instanceof DateTimeInterface) return true; | ||||
|     if (is_int($datetime)) return true; | ||||
|     if (is_string($datetime)) { | ||||
|       return preg_match(_utils::DMYHIS_PATTERN, $datetime) || | ||||
|         (!$frOnly && preg_match(_utils::YMDHISZ_PATTERN, $datetime)); | ||||
|     } | ||||
|     if (is_array($datetime)) return _utils::parse_array($datetime) !== null; | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   static function isa_date($date, bool $frOnly=false): bool { | ||||
|     if ($date === null) return false; | ||||
|     if ($date instanceof DateTimeInterface) return true; | ||||
|     if (is_int($date)) return true; | ||||
|     if (is_string($date)) { | ||||
|       return preg_match(_utils::DMY_PATTERN, $date) || | ||||
|         (!$frOnly && preg_match(_utils::YMD_PATTERN, $date)); | ||||
|     } | ||||
|     if (is_array($date)) return _utils::parse_array($date) !== null; | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   function diff($target, $absolute=false): DateInterval { | ||||
|     return new DateInterval(parent::diff($target, $absolute)); | ||||
|   } | ||||
| 
 | ||||
|   function format($format=self::DEFAULT_FORMAT): string { | ||||
|     if (array_key_exists($format, _utils::INT_FORMATS)) { | ||||
|       $format = _utils::INT_FORMATS[$format]; | ||||
|     } elseif (array_key_exists($format, _utils::STRING_FORMATS)) { | ||||
|       $format = _utils::STRING_FORMATS[$format]; | ||||
|     } | ||||
|     if (is_callable($format)) return $format($this); | ||||
|     else return parent::format($format); | ||||
|   } | ||||
| 
 | ||||
|   function __toString(): string { | ||||
|     return $this->format(); | ||||
|   } | ||||
| 
 | ||||
|   function __get($name) { | ||||
|     if (array_key_exists($name, _utils::INT_FORMATS)) { | ||||
|       $format = _utils::INT_FORMATS[$name]; | ||||
|       if (is_callable($format)) return intval($format($this)); | ||||
|       else return intval($this->format($format)); | ||||
|     } elseif (array_key_exists($name, _utils::STRING_FORMATS)) { | ||||
|       $format = _utils::STRING_FORMATS[$name]; | ||||
|       if (is_callable($format)) return $format($this); | ||||
|       else return $this->format($format); | ||||
|     } | ||||
|     throw new InvalidArgumentException("Unknown property $name"); | ||||
|   } | ||||
| 
 | ||||
|   function getElapsedAt(?DateTimeInterface $now=null, ?int $resolution=null): string { | ||||
|     return Elapsed::format_at($this, $now, $resolution); | ||||
|   } | ||||
| 
 | ||||
|   function getElapsedSince(?DateTimeInterface $now=null, ?int $resolution=null): string { | ||||
|     return Elapsed::format_since($this, $now, $resolution); | ||||
|   } | ||||
| 
 | ||||
|   function getElapsedDelay(?DateTimeInterface $now=null, ?int $resolution=null): string { | ||||
|     return Elapsed::format_delay($this, $now, $resolution); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										147
									
								
								php/src/php/time/_utils.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										147
									
								
								php/src/php/time/_utils.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,147 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use nulib\str; | ||||
| 
 | ||||
| class _utils { | ||||
|   const DMY_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))?$/'; | ||||
|   const YMD_PATTERN = '/^((?:\d{2})?\d{2})(\d{2})(\d{2})$/'; | ||||
|   const DMYHIS_PATTERN = '/^(\d+)\/(\d+)(?:\/(\d+))? +(\d+)[h:.](\d+)(?:[:.](\d+))?$/'; | ||||
|   const YMDHISZ_PATTERN = '/^((?:\d{2})?\d{2})-?(\d{2})-?(\d{2})[tT](\d{2}):?(\d{2}):?(\d{2})?([zZ]|\+\d{2}:?\d{2})?$/'; | ||||
| 
 | ||||
|   /** retourner le nombre de secondes depuis minuit */ | ||||
|   static function _nbsecs_format(\DateTimeInterface $datetime): string { | ||||
|     [$h, $m, $s] = explode(",", $datetime->format("H,i,s")); | ||||
|     return $h * 3600 + $m * 60 + $s; | ||||
|   } | ||||
| 
 | ||||
|   static function _YmdHMSZ_format(\DateTimeInterface $datetime): string { | ||||
|     $YmdHMS = $datetime->format("Ymd\\THis"); | ||||
|     $Z = $datetime->format("P"); | ||||
|     if ($Z === "+00:00") $Z = "Z"; | ||||
|     return "$YmdHMS$Z"; | ||||
|   } | ||||
| 
 | ||||
|   const INT_FORMATS = [ | ||||
|     "year" => "Y", | ||||
|     "month" => "m", | ||||
|     "day" => "d", | ||||
|     "hour" => "H", | ||||
|     "minute" => "i", | ||||
|     "second" => "s", | ||||
|     "wday" => "N", | ||||
|     "wnum" => "W", | ||||
|     "nbsecs" => [self::class, "_nbsecs_format"], | ||||
|   ]; | ||||
|   const STRING_FORMATS = [ | ||||
|     "timezone" => "P", | ||||
|     "datetime" => "d/m/Y H:i:s", | ||||
|     "date" => "d/m/Y", | ||||
|     "Ymd" => "Ymd", | ||||
|     "YmdHMS" => "Ymd\\THis", | ||||
|     "YmdHMSZ" => [self::class, "_YmdHMSZ_format"], | ||||
|   ]; | ||||
| 
 | ||||
|   /** | ||||
|    * corriger une année à deux chiffres qui est située dans le passé et | ||||
|    * retourner l'année à 4 chiffres. | ||||
|    * | ||||
|    * par exemple, si l'année courante est 2019, alors: | ||||
|    * - fix_past_year('18') === '2018' | ||||
|    * - fix_past_year('19') === '1919' | ||||
|    * - fix_past_year('20') === '1920' | ||||
|    */ | ||||
|   static function fix_past_year(int $year): int { | ||||
|     if ($year < 100) { | ||||
|       $y = getdate(); | ||||
|       $y = $y["year"]; | ||||
|       $r = $y % 100; | ||||
|       $c = $y - $r; | ||||
|       if ($year >= $r) $year += $c - 100; | ||||
|       else $year += $c; | ||||
|     } | ||||
|     return $year; | ||||
|   } | ||||
| 
 | ||||
|   /** | ||||
|    * corriger une année à deux chiffres et retourner l'année à 4 chiffres. | ||||
|    * l'année charnière entre année passée et année future est 70 | ||||
|    * | ||||
|    * par exemple, si l'année courante est 2019, alors: | ||||
|    * - fix_past_year('18') === '2018' | ||||
|    * - fix_past_year('19') === '2019' | ||||
|    * - fix_past_year('20') === '2020' | ||||
|    * - fix_past_year('69') === '2069' | ||||
|    * - fix_past_year('70') === '1970' | ||||
|    * - fix_past_year('71') === '1971' | ||||
|    */ | ||||
|   static function fix_any_year(int $year): int { | ||||
|     if ($year < 100) { | ||||
|       $y = intval(date("Y")); | ||||
|       $r = $y % 100; | ||||
|       $c = $y - $r; | ||||
|       if ($year >= 70) $year += $c - 100; | ||||
|       else $year += $c; | ||||
|     } | ||||
|     return $year; | ||||
|   } | ||||
| 
 | ||||
|   static function fix_z(?string $Z): ?string { | ||||
|     $Z = strtoupper($Z); | ||||
|     str::del_prefix($Z, "+"); | ||||
|     if (preg_match('/^\d{4}$/', $Z)) { | ||||
|       $Z = substr($Z, 0, 2) . ":" . substr($Z, 2); | ||||
|     } | ||||
|     if ($Z === "Z" || $Z === "UTC" || $Z === "00:00") return "UTC"; | ||||
|     return "GMT+$Z"; | ||||
|   } | ||||
| 
 | ||||
|   static function get_value(array $datetime, ?string $key, ?string $k, ?int $index) { | ||||
|     $value = null; | ||||
|     if ($value === null && $key !== null) $value = $datetime[$key] ?? null; | ||||
|     if ($value === null && $k !== null) $value = $datetime[$k] ?? null; | ||||
|     if ($value === null && $index !== null) $value = $datetime[$index] ?? null; | ||||
|     return $value; | ||||
|   } | ||||
| 
 | ||||
|   static function parse_int(array $datetime, ?string $key, ?string $k, ?int $index, ?int &$part, bool $required = true, ?int $default = null): bool { | ||||
|     $part = null; | ||||
|     $value = self::get_value($datetime, $key, $k, $index); | ||||
|     if ($value === null) { | ||||
|       if ($required && $default === null) return false; | ||||
|       $part = $default; | ||||
|       return true; | ||||
|     } | ||||
|     if (is_numeric($value)) { | ||||
|       $part = intval($value); | ||||
|       return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   static function parse_str(array $datetime, ?string $key, ?string $k, ?int $index, ?string &$part, bool $required = true, ?string $default = null): bool { | ||||
|     $part = null; | ||||
|     $value = self::get_value($datetime, $key, $k, $index); | ||||
|     if ($value === null) { | ||||
|       if ($required && $default === null) return false; | ||||
|       $part = $default; | ||||
|       return true; | ||||
|     } | ||||
|     if (is_string($value)) { | ||||
|       $part = $value; | ||||
|       return true; | ||||
|     } | ||||
|     return false; | ||||
|   } | ||||
| 
 | ||||
|   static function parse_array(array $datetime): ?array { | ||||
|     if (!self::parse_int($datetime, "year", "Y", 0, $year)) return null; | ||||
|     if (!self::parse_int($datetime, "month", "m", 1, $month)) return null; | ||||
|     if (!self::parse_int($datetime, "day", "d", 2, $day)) return null; | ||||
|     self::parse_int($datetime, "hour", "H", 3, $hour, false); | ||||
|     self::parse_int($datetime, "minute", "M", 4, $minute, false); | ||||
|     self::parse_int($datetime, "second", "S", 5, $second, false); | ||||
|     self::parse_str($datetime, "tz", null, 6, $tz, false); | ||||
|     return [$year, $month, $day, $hour, $minute, $second, $tz]; | ||||
|   } | ||||
| } | ||||
| @ -29,13 +29,15 @@ class DateTest extends TestCase { | ||||
| 
 | ||||
|   function testClone() { | ||||
|     $date = self::dt("now"); | ||||
|     $clone = $date->clone(true); | ||||
|     self::assertInstanceOf(MutableDate::class, $clone); | ||||
|     $clone = $date->clone(); | ||||
|     self::assertInstanceOf(DateTime::class, $clone); | ||||
|     self::assertInstanceOf(Date::class, $clone); | ||||
|   } | ||||
| 
 | ||||
|   function testConstruct() { | ||||
|     $y = date("Y"); | ||||
|     self::assertSame("05/04/$y", strval(new Date("5/4"))); | ||||
|     $Y = date("Y"); | ||||
|     self::assertSame("05/04/$Y", strval(new Date("5/4"))); | ||||
|     self::assertSame("05/04/2024", strval(new Date("5/4/24"))); | ||||
|     self::assertSame("05/04/2024", strval(new Date("5/4/2024"))); | ||||
|     self::assertSame("05/04/2024", strval(new Date("05/04/2024"))); | ||||
|  | ||||
| @ -5,12 +5,8 @@ use DateTimeZone; | ||||
| use nulib\tests\TestCase; | ||||
| 
 | ||||
| class DateTimeTest extends TestCase { | ||||
|   protected static function dt(string $datetime): DateTime { | ||||
|     return new DateTime($datetime, new DateTimeZone("Indian/Reunion")); | ||||
|   } | ||||
| 
 | ||||
|   function testDateTime() { | ||||
|     $date = self::dt("2024-04-05 09:15:23"); | ||||
|     $date = new DateTime("2024-04-05 09:15:23"); | ||||
| 
 | ||||
|     self::assertEquals("05/04/2024 09:15:23", $date->format()); | ||||
|     self::assertEquals("05/04/2024 09:15:23", strval($date)); | ||||
| @ -31,24 +27,36 @@ 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); | ||||
|     $date = new DateTime("20240405T091523"); | ||||
|     self::assertSame("20240405T091523+04:00", $date->YmdHMSZ); | ||||
| 
 | ||||
|     $date = new DateTime("20240405T091523+02:00", null, null); | ||||
|     self::assertSame("20240405T111523+04:00", $date->YmdHMSZ); | ||||
|     $date = new DateTime("20240405T091523+02:00", null, true); | ||||
|     self::assertSame("20240405T111523+04:00", $date->YmdHMSZ); | ||||
|     $date = new DateTime("20240405T091523+02:00", null, false); | ||||
|     self::assertSame("20240405T091523+02:00", $date->YmdHMSZ); | ||||
| 
 | ||||
|     $newtz = new DateTimeZone("+06:00"); | ||||
|     $date = new DateTime("20240405T091523+02:00", $newtz, null); | ||||
|     self::assertSame("20240405T091523+02:00", $date->YmdHMSZ); | ||||
|     $date = new DateTime("20240405T091523+02:00", $newtz, false); | ||||
|     self::assertSame("20240405T091523+02:00", $date->YmdHMSZ); | ||||
|     $date = new DateTime("20240405T091523+02:00", $newtz, true); | ||||
|     self::assertSame("20240405T131523+06:00", $date->YmdHMSZ); | ||||
|   } | ||||
| 
 | ||||
|   function testClone() { | ||||
|     $date = self::dt("now"); | ||||
|     $date = new DateTime("now"); | ||||
|     $clone = $date->clone(true); | ||||
|     self::assertInstanceOf(MutableDateTime::class, $clone); | ||||
|     $clone = $date->clone(); | ||||
|     self::assertInstanceOf(DateTime::class, $clone); | ||||
|   } | ||||
| 
 | ||||
|   function testConstruct() { | ||||
|     $y = date("Y"); | ||||
|     self::assertSame("05/04/$y 00:00:00", strval(new DateTime("5/4"))); | ||||
|     $Y = date("Y"); | ||||
|     self::assertSame("05/04/$Y 00:00:00", strval(new DateTime("5/4"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new DateTime("5/4/24"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new DateTime("5/4/2024"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new DateTime("05/04/2024"))); | ||||
|  | ||||
| @ -5,72 +5,68 @@ use DateTimeZone; | ||||
| use nulib\tests\TestCase; | ||||
| 
 | ||||
| class DelayTest extends TestCase { | ||||
|   protected static function dt(string $datetime): DateTime { | ||||
|     return new DateTime($datetime, new DateTimeZone("Indian/Reunion")); | ||||
|   } | ||||
| 
 | ||||
|   function testDelay() { | ||||
|     $from = self::dt("2024-04-05 09:15:23"); | ||||
|     $from = new MutableDateTime("2024-04-05 09:15:23"); | ||||
| 
 | ||||
|     $delay = new Delay(10, $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:15:33"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:15:33"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("10", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:15:33"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:15:33"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("10s", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:15:33"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:15:33"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("s", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:15:24"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:15:24"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5m", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:20:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:20:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5m0", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:20:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:20:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5m2", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:20:02"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:20:02"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("m", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 09:16:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 09:16:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5h", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 14:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 14:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5h0", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 14:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 14:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5h2", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 14:02:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 14:02:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("h", $from); | ||||
|     self::assertEquals(self::dt("2024-04-05 10:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-05 10:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5d", $from); | ||||
|     self::assertEquals(self::dt("2024-04-10 05:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-10 05:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5d2", $from); | ||||
|     self::assertEquals(self::dt("2024-04-10 02:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-10 02:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("5d0", $from); | ||||
|     self::assertEquals(self::dt("2024-04-10 00:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-10 00:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("d", $from); | ||||
|     self::assertEquals(self::dt("2024-04-06 05:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-06 05:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("2w", $from); | ||||
|     self::assertEquals(self::dt("2024-04-21 05:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-21 05:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("2w2", $from); | ||||
|     self::assertEquals(self::dt("2024-04-21 02:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-21 02:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("2w0", $from); | ||||
|     self::assertEquals(self::dt("2024-04-21 00:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-21 00:00:00"), $delay->getDest()); | ||||
| 
 | ||||
|     $delay = new Delay("w", $from); | ||||
|     self::assertEquals(self::dt("2024-04-07 05:00:00"), $delay->getDest()); | ||||
|     self::assertEquals(new MutableDateTime("2024-04-07 05:00:00"), $delay->getDest()); | ||||
|   } | ||||
| 
 | ||||
|   function testElapsed() { | ||||
|  | ||||
							
								
								
									
										87
									
								
								php/tests/php/time/MutableDateTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								php/tests/php/time/MutableDateTest.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeZone; | ||||
| use nulib\tests\TestCase; | ||||
| 
 | ||||
| class MutableDateTest extends TestCase { | ||||
|   protected static function dt(string $datetime): MutableDate { | ||||
|     return new MutableDate($datetime, new DateTimeZone("Indian/Reunion")); | ||||
|   } | ||||
| 
 | ||||
|   function testDate() { | ||||
|     $date = self::dt("2024-04-05 09:15:23"); | ||||
| 
 | ||||
|     self::assertSame("05/04/2024", $date->format()); | ||||
|     self::assertSame("05/04/2024", strval($date)); | ||||
|     self::assertSame(2024, $date->year); | ||||
|     self::assertSame(4, $date->month); | ||||
|     self::assertSame(5, $date->day); | ||||
|     self::assertSame(0, $date->hour); | ||||
|     self::assertSame(0, $date->minute); | ||||
|     self::assertSame(0, $date->second); | ||||
|     self::assertSame(5, $date->wday); | ||||
|     self::assertSame(14, $date->wnum); | ||||
|     self::assertSame("+04:00", $date->timezone); | ||||
|     self::assertSame("05/04/2024 00:00:00", $date->datetime); | ||||
|     self::assertSame("05/04/2024", $date->date); | ||||
|   } | ||||
| 
 | ||||
|   function testClone() { | ||||
|     $date = self::dt("now"); | ||||
|     $clone = $date->clone(true); | ||||
|     self::assertInstanceOf(MutableDate::class, $clone); | ||||
|     $clone = $date->clone(); | ||||
|     self::assertInstanceOf(Date::class, $clone); | ||||
|   } | ||||
| 
 | ||||
|   function testConstruct() { | ||||
|     $Y = date("Y"); | ||||
|     self::assertSame("05/04/$Y", strval(new MutableDate("5/4"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/24"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("05/04/2024"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("20240405"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("240405"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("20240405T091523"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("20240405T091523Z"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 9:15:23"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 9.15.23"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 9:15"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 9.15"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 9h15"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 09:15:23"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 09:15"))); | ||||
|     self::assertSame("05/04/2024", strval(new MutableDate("5/4/2024 09h15"))); | ||||
|   } | ||||
| 
 | ||||
|   function testCompare() { | ||||
|     $a = new MutableDate("10/02/2024"); | ||||
|     $b = new MutableDate("15/02/2024"); | ||||
|     $c = new MutableDate("20/02/2024"); | ||||
|     $a2 = new MutableDate("10/02/2024"); | ||||
|     $b2 = new MutableDate("15/02/2024"); | ||||
|     $c2 = new MutableDate("20/02/2024"); | ||||
| 
 | ||||
|     self::assertTrue($a == $a2); | ||||
|     self::assertFalse($a === $a2); | ||||
|     self::assertTrue($b == $b2); | ||||
|     self::assertTrue($c == $c2); | ||||
| 
 | ||||
|     self::assertFalse($a < $a); | ||||
|     self::assertTrue($a < $b); | ||||
|     self::assertTrue($a < $c); | ||||
| 
 | ||||
|     self::assertTrue($a <= $a); | ||||
|     self::assertTrue($a <= $b); | ||||
|     self::assertTrue($a <= $c); | ||||
| 
 | ||||
|     self::assertFalse($c > $c); | ||||
|     self::assertTrue($c > $b); | ||||
|     self::assertTrue($c > $a); | ||||
| 
 | ||||
|     self::assertTrue($c >= $c); | ||||
|     self::assertTrue($c >= $b); | ||||
|     self::assertTrue($c >= $a); | ||||
|   } | ||||
| } | ||||
							
								
								
									
										121
									
								
								php/tests/php/time/MutableDateTimeTest.php
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										121
									
								
								php/tests/php/time/MutableDateTimeTest.php
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,121 @@ | ||||
| <?php | ||||
| namespace nulib\php\time; | ||||
| 
 | ||||
| use DateTimeZone; | ||||
| use nulib\tests\TestCase; | ||||
| 
 | ||||
| class MutableDateTimeTest extends TestCase { | ||||
|   function testDateTime() { | ||||
|     $date = new MutableDateTime("2024-04-05 09:15:23"); | ||||
| 
 | ||||
|     self::assertEquals("05/04/2024 09:15:23", $date->format()); | ||||
|     self::assertEquals("05/04/2024 09:15:23", strval($date)); | ||||
|     self::assertSame(2024, $date->year); | ||||
|     self::assertSame(4, $date->month); | ||||
|     self::assertSame(5, $date->day); | ||||
|     self::assertSame(9, $date->hour); | ||||
|     self::assertSame(15, $date->minute); | ||||
|     self::assertSame(23, $date->second); | ||||
|     self::assertSame(5, $date->wday); | ||||
|     self::assertSame(14, $date->wnum); | ||||
|     self::assertEquals("+04:00", $date->timezone); | ||||
|     self::assertSame("05/04/2024 09:15:23", $date->datetime); | ||||
|     self::assertSame("05/04/2024", $date->date); | ||||
|     self::assertSame("20240405", $date->Ymd); | ||||
|     self::assertSame("20240405T091523", $date->YmdHMS); | ||||
|     self::assertSame("20240405T091523+04:00", $date->YmdHMSZ); | ||||
|   } | ||||
| 
 | ||||
|   function testDateTimeZ() { | ||||
|     $date = new MutableDateTime("20240405T091523"); | ||||
|     self::assertSame("20240405T091523+04:00", $date->YmdHMSZ); | ||||
| 
 | ||||
|     $date = new MutableDateTime("20240405T091523+02:00", null, null); | ||||
|     self::assertSame("20240405T111523+04:00", $date->YmdHMSZ); | ||||
|     $date = new MutableDateTime("20240405T091523+02:00", null, true); | ||||
|     self::assertSame("20240405T111523+04:00", $date->YmdHMSZ); | ||||
|     $date = new MutableDateTime("20240405T091523+02:00", null, false); | ||||
|     self::assertSame("20240405T091523+02:00", $date->YmdHMSZ); | ||||
| 
 | ||||
|     $newtz = new DateTimeZone("+06:00"); | ||||
|     $date = new MutableDateTime("20240405T091523+02:00", $newtz, null); | ||||
|     self::assertSame("20240405T091523+02:00", $date->YmdHMSZ); | ||||
|     $date = new MutableDateTime("20240405T091523+02:00", $newtz, false); | ||||
|     self::assertSame("20240405T091523+02:00", $date->YmdHMSZ); | ||||
|     $date = new MutableDateTime("20240405T091523+02:00", $newtz, true); | ||||
|     self::assertSame("20240405T131523+06:00", $date->YmdHMSZ); | ||||
|   } | ||||
| 
 | ||||
|   function testClone() { | ||||
|     $date = new MutableDateTime("now"); | ||||
|     $clone = $date->clone(true); | ||||
|     self::assertInstanceOf(MutableDateTime::class, $clone); | ||||
|     $clone = $date->clone(); | ||||
|     self::assertInstanceOf(DateTime::class, $clone); | ||||
|   } | ||||
| 
 | ||||
|   function testConstruct() { | ||||
|     $Y = date("Y"); | ||||
|     self::assertSame("05/04/$Y 00:00:00", strval(new MutableDateTime("5/4"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new MutableDateTime("5/4/24"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new MutableDateTime("5/4/2024"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new MutableDateTime("05/04/2024"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new MutableDateTime("20240405"))); | ||||
|     self::assertSame("05/04/2024 00:00:00", strval(new MutableDateTime("240405"))); | ||||
|     self::assertSame("05/04/2024 09:15:23", strval(new MutableDateTime("20240405T091523"))); | ||||
|     self::assertSame("05/04/2024 13:15:23", strval(new MutableDateTime("20240405T091523Z"))); | ||||
|     self::assertSame("05/04/2024 09:15:23", strval(new MutableDateTime("5/4/2024 9:15:23"))); | ||||
|     self::assertSame("05/04/2024 09:15:23", strval(new MutableDateTime("5/4/2024 9.15.23"))); | ||||
|     self::assertSame("05/04/2024 09:15:00", strval(new MutableDateTime("5/4/2024 9:15"))); | ||||
|     self::assertSame("05/04/2024 09:15:00", strval(new MutableDateTime("5/4/2024 9.15"))); | ||||
|     self::assertSame("05/04/2024 09:15:00", strval(new MutableDateTime("5/4/2024 9h15"))); | ||||
|     self::assertSame("05/04/2024 09:15:23", strval(new MutableDateTime("5/4/2024 09:15:23"))); | ||||
|     self::assertSame("05/04/2024 09:15:00", strval(new MutableDateTime("5/4/2024 09:15"))); | ||||
|     self::assertSame("05/04/2024 09:15:00", strval(new MutableDateTime("5/4/2024 09h15"))); | ||||
|   } | ||||
| 
 | ||||
|   function testCompare() { | ||||
|     $a = new MutableDateTime("10/02/2024"); | ||||
|     $a2 = new MutableDateTime("10/02/2024 8:30"); | ||||
|     $a3 = new MutableDateTime("10/02/2024 15:45"); | ||||
|     $b = new MutableDateTime("15/02/2024"); | ||||
|     $b2 = new MutableDateTime("15/02/2024 8:30"); | ||||
|     $b3 = new MutableDateTime("15/02/2024 15:45"); | ||||
|     $x = new MutableDateTime("10/02/2024"); | ||||
|     $x2 = new MutableDateTime("10/02/2024 8:30"); | ||||
|     $x3 = new MutableDateTime("10/02/2024 15:45"); | ||||
| 
 | ||||
|     self::assertTrue($a == $x); | ||||
|     self::assertFalse($a === $x); | ||||
|     self::assertTrue($a2 == $x2); | ||||
|     self::assertTrue($a3 == $x3); | ||||
| 
 | ||||
|     self::assertFalse($a < $a); | ||||
|     self::assertTrue($a < $a2); | ||||
|     self::assertTrue($a < $a3); | ||||
|     self::assertTrue($a < $b); | ||||
|     self::assertTrue($a < $b2); | ||||
|     self::assertTrue($a < $b3); | ||||
| 
 | ||||
|     self::assertTrue($a <= $a); | ||||
|     self::assertTrue($a <= $a2); | ||||
|     self::assertTrue($a <= $a3); | ||||
|     self::assertTrue($a <= $b); | ||||
|     self::assertTrue($a <= $b2); | ||||
|     self::assertTrue($a <= $b3); | ||||
| 
 | ||||
|     self::assertTrue($b > $a); | ||||
|     self::assertTrue($b > $a2); | ||||
|     self::assertTrue($b > $a3); | ||||
|     self::assertFalse($b > $b); | ||||
|     self::assertFalse($b > $b2); | ||||
|     self::assertFalse($b > $b3); | ||||
| 
 | ||||
|     self::assertTrue($b >= $a); | ||||
|     self::assertTrue($b >= $a2); | ||||
|     self::assertTrue($b >= $a3); | ||||
|     self::assertTrue($b >= $b); | ||||
|     self::assertFalse($b >= $b2); | ||||
|     self::assertFalse($b >= $b3); | ||||
|   } | ||||
| } | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user