$now->between($from, $to), $from !== null => $now->greaterThanOrEqualTo($from), $to !== null => $now->lessThanOrEqualTo($to), default => false, }; } public static function toRfc3339(\DateTimeInterface | string $datetime): string { $datetime = is_string($datetime) ? self::parseDateTime($datetime) : $datetime; return $datetime->format(\DATE_RFC3339); } public static function parseDateTime(string $datetime): \DateTimeInterface { $datetime = trim($datetime); /** @var \DateTimeInterface|null */ $output = null; switch (true) { case (bool) preg_match(self::FRENCH_DATE_REGEX, $datetime): $output = self::parseFrench($datetime); break; case (bool) preg_match(self::FRENCH_DATE_INVERT_REGEX, $datetime): $output = self::parseFrenchInverted($datetime); break; case (bool) preg_match(self::RFC3339_REGEX, $datetime): $output = self::parseRfc3339($datetime); break; case (bool) preg_match(self::ISO8601_REGEX, $datetime): $output = self::parseIso8601($datetime); break; default: try { $output = new \DateTimeImmutable($datetime); } catch (\Exception) { throw new \InvalidArgumentException('Unrecognized date/time format: ' . $datetime); } } return $output; } protected static function parseFrench(string $datetime): \DateTimeInterface { $dt = \DateTimeImmutable::createFromFormat('Y-m-d H:i:s', $datetime . ' 00:00:00'); return $dt ?: self::parseFallback($datetime); } protected static function parseFrenchInverted(string $datetime): \DateTimeInterface { $dt = \DateTimeImmutable::createFromFormat('d-m-Y H:i:s', $datetime . ' 00:00:00'); return $dt ?: self::parseFallback($datetime); } protected static function parseRfc3339(string $datetime): \DateTimeInterface { $dt = \DateTimeImmutable::createFromFormat(\DateTime::RFC3339, $datetime); if ($dt !== false) { return $dt; } $dt = \DateTimeImmutable::createFromFormat('Y-m-d\TH:i:s.uP', $datetime); return $dt ?: self::parseFallback($datetime); } protected static function parseIso8601(string $datetime): \DateTimeInterface { $dt = \DateTimeImmutable::createFromFormat(\DateTimeInterface::ATOM, $datetime); return $dt ?: self::parseFallback($datetime); } protected static function parseFallback(string $datetime): \DateTimeInterface { try { return new \DateTimeImmutable($datetime); } catch (\Throwable) { throw new \InvalidArgumentException("Unrecognized date/time format: {$datetime}"); } } }