diff --git a/src/StaticClass.php b/src/StaticClass.php index c719e3b6f..e76925636 100644 --- a/src/StaticClass.php +++ b/src/StaticClass.php @@ -16,12 +16,10 @@ trait StaticClass { /** - * @return never - * @throws \Error + * Class is static and cannot be instantiated. */ - final public function __construct() + final private function __construct() { - throw new \Error('Class ' . static::class . ' is static and cannot be instantiated.'); } diff --git a/src/Utils/DateTime.php b/src/Utils/DateTime.php index 963407c0d..993f55e09 100644 --- a/src/Utils/DateTime.php +++ b/src/Utils/DateTime.php @@ -14,10 +14,27 @@ /** * DateTime. + * @property-read int $timestamp + * @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 $microsecond + * @property-read int $millisecond + * @property-read string $date + * @property-read string $dateTime + * @property-read string $dateTimeTz + * @property-read string $dateTimeMicro + * @property-read string $dateTimeMicroTz + * @property-read float $timestampMicro + * @property-read int $dayOfWeek */ class DateTime extends \DateTime implements \JsonSerializable { use Nette\SmartObject; + use DateTimeFormat; /** minute in seconds */ public const MINUTE = 60; @@ -125,7 +142,7 @@ public function jsonSerialize(): string */ public function __toString(): string { - return $this->format('Y-m-d H:i:s'); + return $this->getDateTime(); } diff --git a/src/Utils/DateTimeFormat.php b/src/Utils/DateTimeFormat.php new file mode 100644 index 000000000..4d6a16906 --- /dev/null +++ b/src/Utils/DateTimeFormat.php @@ -0,0 +1,110 @@ +format('Y'); + } + + + public function getMonth(): int + { + return (int) $this->format('n'); + } + + + public function getDay(): int + { + return (int) $this->format('j'); + } + + + public function getHour(): int + { + return (int) $this->format('G'); + } + + + public function getMinute(): int + { + return (int) $this->format('i'); + } + + + public function getSecond(): int + { + return (int) $this->format('s'); + } + + + public function getMicrosecond(): int + { + return (int) $this->format('u'); + } + + + public function getMillisecond(): int + { + return (int) $this->format('v'); + } + + + public function getDate(): string + { + return $this->format('Y-m-d'); + } + + + public function getDateTime(): string + { + return $this->format('Y-m-d H:i:s'); + } + + + public function getDateTimeTz(): string + { + return $this->format('Y-m-d H:i:sO'); + } + + + public function getDateTimeMicro(): string + { + $micro = rtrim($this->format('u'), '0'); + if ($micro === '') { + $micro = '0'; + } + + return $this->format('Y-m-d H:i:s.') . $micro; + } + + + public function getDateTimeMicroTz(): string + { + return $this->getDateTimeMicro() . $this->format('O'); + } + + + public function getTimestampMicro(): float + { + return (float) $this->format('U.u'); + } + + + public function getDayOfWeek(): int + { + return (int) $this->format('N'); + } +} diff --git a/src/Utils/Finder.php b/src/Utils/Finder.php index 1f3ea589c..d17687c55 100644 --- a/src/Utils/Finder.php +++ b/src/Utils/Finder.php @@ -337,7 +337,7 @@ public function getIterator(): \Generator /** - * @param array<\stdClass{pattern: string, mode: string, recursive: bool}> $searches + * @param array $searches * @param string[] $subdirs * @return \Generator */ @@ -427,7 +427,7 @@ private function proveFilters(array $filters, FileInfo $file, array &$cache): bo } - /** @return array> */ + /** @return array> */ private function buildPlan(): array { $plan = $dirCache = []; diff --git a/src/Utils/Strings.php b/src/Utils/Strings.php index 378ceee63..2a649ea7e 100644 --- a/src/Utils/Strings.php +++ b/src/Utils/Strings.php @@ -397,9 +397,11 @@ public static function findPrefix(array $strings): string */ public static function length(string $s): int { - return function_exists('mb_strlen') - ? mb_strlen($s, 'UTF-8') - : strlen(utf8_decode($s)); + return match (true) { + extension_loaded('mbstring') => mb_strlen($s, 'UTF-8'), + extension_loaded('iconv') => iconv_strlen($s, 'UTF-8'), + default => strlen(@utf8_decode($s)), // deprecated + }; } diff --git a/tests/Utils/DateTimeFormat.properties.phpt b/tests/Utils/DateTimeFormat.properties.phpt new file mode 100644 index 000000000..86c96c8f0 --- /dev/null +++ b/tests/Utils/DateTimeFormat.properties.phpt @@ -0,0 +1,41 @@ +year); +Assert::same(1, DateTime::from('1978-01-23 11:40:00.86')->month); +Assert::same(23, DateTime::from('1978-01-23 11:40:00.86')->day); +Assert::same(11, DateTime::from('1978-01-23 11:40:00.86')->hour); +Assert::same(40, DateTime::from('1978-01-23 11:40:00.86')->minute); +Assert::same(0, DateTime::from('1978-01-23 11:40:00.86')->second); +Assert::same(863500, DateTime::from('1978-01-23 11:40:00.8635')->microsecond); +Assert::same(863, DateTime::from('1978-01-23 11:40:00.8635')->millisecond); +Assert::same('1978-01-23', DateTime::from('1978-01-23 11:40:00.86')->date); +Assert::same('1978-01-23 11:40:00', DateTime::from('1978-01-23 11:40:00.86')->dateTime); +Assert::same('1978-01-23 11:40:00+0100', DateTime::from('1978-01-23 11:40:00.86')->dateTimeTz); +Assert::same('1978-01-23 11:40:00.86', DateTime::from('1978-01-23 11:40:00.860000')->dateTimeMicro); +Assert::same('1978-01-23 11:40:00.0', DateTime::from('1978-01-23 11:40:00.000000')->dateTimeMicro); +Assert::same('1978-01-23 11:40:00.86+0100', DateTime::from('1978-01-23 11:40:00.860000')->dateTimeMicroTz); +Assert::same(254_400_000.86, DateTime::from('1978-01-23 11:40:00.860000')->timestampMicro); +Assert::same(254_400_000, DateTime::from('1978-01-23 11:40:00.860000')->timestamp); +Assert::same(1, DateTime::from('1978-01-23 11:40:00.860000')->dayOfWeek); + +/** + * reverse engineering does not work, it is reason why keep zero for microsecond + * @see \Nette\Utils\DateTimeFormat::getDateTimeMicro() + */ +Assert::type(DateTime::class, DateTime::createFromFormat('Y-m-d H:i:s.u', '1978-01-23 11:40:00.0')); +Assert::false(DateTime::createFromFormat('Y-m-d H:i:s.u', '1978-01-23 11:40:00.')); +Assert::false(DateTime::createFromFormat('Y-m-d H:i:s.u', '1978-01-23 11:40:00')); diff --git a/tests/Utils/StaticClass.phpt b/tests/Utils/StaticClass.phpt index 01d87d38e..435a24821 100644 --- a/tests/Utils/StaticClass.phpt +++ b/tests/Utils/StaticClass.phpt @@ -23,7 +23,7 @@ class TestClass Assert::exception( fn() => new TestClass, Error::class, - 'Class TestClass is static and cannot be instantiated.', + 'Call to private TestClass::__construct() from global scope', ); Assert::exception(