diff --git a/src/TimeShift.php b/src/TimeShift.php index fce8b61..8a2f53b 100644 --- a/src/TimeShift.php +++ b/src/TimeShift.php @@ -7,6 +7,7 @@ use CloudCastle\Clock\Exception\InvalidClockValueException; use DateMalformedStringException; use DateTimeImmutable; +use ReflectionMethod; /** * Применение строки-модификатора к моменту с полной валидацией. @@ -46,7 +47,7 @@ public static function apply(DateTimeImmutable $moment, string $modifier): DateT throw InvalidClockValueException::invalidModifier($modifier); } - if ($shifted === false) { + if (!$shifted instanceof DateTimeImmutable) { throw InvalidClockValueException::invalidModifier($modifier); } @@ -54,15 +55,18 @@ public static function apply(DateTimeImmutable $moment, string $modifier): DateT } /** - * Сырой вызов `modify()` с широкой сигнатурой. + * Сырой вызов `modify()` с непрозрачным для анализаторов результатом. * - * До PHP 8.3 провал возвращает `false`, с 8.3 — бросает - * {@see \DateMalformedStringException}; широкий тип возврата делает - * обработку обоих каналов корректной для анализаторов на всей - * матрице PHP 8.1–8.5. + * Тип возврата родного `modify()` различается между эпохами стабов + * (до PHP 8.3 — `DateTimeImmutable|false`, с 8.3 — только момент, + * хотя tentative-совместимые наследники могут вернуть `false` на любой + * версии), поэтому прямой вызов не проходит строгий анализ одновременно + * на всей матрице 8.1–8.5. Рефлексия возвращает `mixed`: вызывающий + * обязан проверить результат, и ветка провала честно достижима везде. + * Путь не горячий — сюда попадают только строковые модификаторы. */ - private static function rawModify(DateTimeImmutable $moment, string $modifier): DateTimeImmutable|false + private static function rawModify(DateTimeImmutable $moment, string $modifier): mixed { - return $moment->modify($modifier); + return (new ReflectionMethod($moment, 'modify'))->invoke($moment, $modifier); } }