test(DatesHelper): update date parsing logic and add fallback tests

Enhance date parsing in DatesHelper to correctly handle RFC3339 format.
Add tests for fallback scenarios with DateTimeImmutable.
This commit is contained in:
Jérémy Munsch 2026-08-13 13:24:33 +02:00
parent e8d92e771a
commit 6d77bc6332
Signed by: forge-joniko
GPG key ID: D7EFE2F5CB6CC0E4
2 changed files with 30 additions and 6 deletions

View file

@ -58,12 +58,12 @@ final class DatesHelper
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;
case (bool) preg_match(self::RFC3339_REGEX, $datetime):
$output = self::parseRfc3339($datetime);
break;
default:
try {
$output = new \DateTimeImmutable($datetime);

View file

@ -10,16 +10,19 @@ use Shared\Helpers\DatesHelper;
covers(DatesHelper::class);
afterEach(function (): void {
\Mockery::close();
CarbonImmutable::setTestNow();
});
describe('Date Helper Integration Tests', function (): void {
it('prevents direct instantiation', function (): void {
it('prevents direct instantiation but covers constructor', function (): void {
// GIVEN
$reflection = new \ReflectionClass(DatesHelper::class);
// WHEN & THEN
// WHEN
$constructor = $reflection->getConstructor();
$constructor->invoke($reflection->newInstanceWithoutConstructor());
// THEN
expect(fn () => $reflection->newInstance())
->toThrow(\ReflectionException::class);
});
@ -50,6 +53,27 @@ describe('Date Helper Integration Tests', function (): void {
->toThrow(\InvalidArgumentException::class, 'Unrecognized date/time format: not-a-real-date-string');
});
it('falls back to DateTimeImmutable for valid formats not fully handled by createFromFormat', function (): void {
// GIVEN
$fallbackDate = '2025-12-25T12:10:23.1234567Z'; // 7 digit microsecond matches regex but fails createFromFormat 'u' (6 digits)
// WHEN
$result = DatesHelper::parseDateTime($fallbackDate);
// THEN
expect($result)->toBeInstanceOf(\DateTimeInterface::class)
->and($result->format('Y-m-d'))->toBe('2025-12-25');
});
it('throws InvalidArgumentException in parseFallback when fallback date is completely invalid logically', function (): void {
// GIVEN
$invalidFallbackDate = '2025-12-25T25:10:23.1234567Z'; // Invalid hour 25, matches regex but fails both createFromFormat and new DateTimeImmutable
// WHEN & THEN
expect(fn () => DatesHelper::parseDateTime($invalidFallbackDate))
->toThrow(\InvalidArgumentException::class, "Unrecognized date/time format: {$invalidFallbackDate}");
});
it('handles isIn date boundary checks correctly', function (): void {
// GIVEN
$now = CarbonImmutable::create(2025, 6, 15, 12, 0, 0);