diff --git a/src/Symfony/Component/Validator/Constraints/Date.php b/src/Symfony/Component/Validator/Constraints/Date.php index add1080798026..245e7f27574b4 100644 --- a/src/Symfony/Component/Validator/Constraints/Date.php +++ b/src/Symfony/Component/Validator/Constraints/Date.php @@ -31,16 +31,18 @@ class Date extends Constraint self::INVALID_DATE_ERROR => 'INVALID_DATE_ERROR', ]; + public string $format = 'Y-m-d'; public string $message = 'This value is not a valid date.'; /** * @param array|null $options * @param string[]|null $groups */ - public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null) + public function __construct(?array $options = null, ?string $message = null, ?array $groups = null, mixed $payload = null, ?string $format = null) { parent::__construct($options, $groups, $payload); $this->message = $message ?? $this->message; + $this->format = $format ?? $this->format; } } diff --git a/src/Symfony/Component/Validator/Constraints/DateValidator.php b/src/Symfony/Component/Validator/Constraints/DateValidator.php index f71c5b376a3d3..068f8b2529781 100644 --- a/src/Symfony/Component/Validator/Constraints/DateValidator.php +++ b/src/Symfony/Component/Validator/Constraints/DateValidator.php @@ -23,16 +23,6 @@ class DateValidator extends ConstraintValidator { public const PATTERN = '/^(?\d{4})-(?\d{2})-(?\d{2})$/D'; - /** - * Checks whether a date is valid. - * - * @internal - */ - public static function checkDate(int $year, int $month, int $day): bool - { - return checkdate($month, $day, $year); - } - public function validate(mixed $value, Constraint $constraint): void { if (!$constraint instanceof Date) { @@ -49,20 +39,14 @@ public function validate(mixed $value, Constraint $constraint): void $value = (string) $value; - if (!preg_match(static::PATTERN, $value, $matches)) { + $asDateTimeImmutable = \DateTimeImmutable::createFromFormat($constraint->format, $value); + + if (!$asDateTimeImmutable) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Date::INVALID_FORMAT_ERROR) ->addViolation(); - - return; - } - - if (!self::checkDate( - $matches['year'] ?? $matches[1], - $matches['month'] ?? $matches[2], - $matches['day'] ?? $matches[3] - )) { + } elseif ($asDateTimeImmutable->format($constraint->format) !== $value) { $this->context->buildViolation($constraint->message) ->setParameter('{{ value }}', $this->formatValue($value)) ->setCode(Date::INVALID_DATE_ERROR) diff --git a/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php b/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php index 93dab41f24622..499f73a2ef463 100644 --- a/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php +++ b/src/Symfony/Component/Validator/Tests/Constraints/DateValidatorTest.php @@ -115,4 +115,58 @@ public static function getInvalidDates() ['2010-02-29', Date::INVALID_DATE_ERROR], ]; } + + /** + * @dataProvider getNotMatchingDatesAndFormats + */ + public function testInvalidFormats($date, $format, $code) + { + $constraint = new Date(message: 'myMessage', format: $format); + + $this->validator->validate($date, $constraint); + + $this->buildViolation('myMessage') + ->setParameter('{{ value }}', '"'.$date.'"') + ->setCode($code) + ->assertRaised(); + } + + public static function getNotMatchingDatesAndFormats(): array + { + return [ + ['2010-03-24', 'm-m-Y', Date::INVALID_FORMAT_ERROR], + ['2010-02-29', 'foo', Date::INVALID_FORMAT_ERROR], + ['bob', 'Y-m-d', Date::INVALID_FORMAT_ERROR], + ['01.05.2030', 'd.m/Y', Date::INVALID_FORMAT_ERROR], + ['01.05.2030', 'd/m-Y', Date::INVALID_FORMAT_ERROR], + ['01.05.2030', 'd/m.Y', Date::INVALID_FORMAT_ERROR], + ]; + } + + /** + * @dataProvider getMatchingDatesAndFormats + */ + public function testValidFormats($date, $format) + { + $this->validator->validate($date, new Date(format: $format)); + + $this->assertNoViolation(); + } + + public static function getMatchingDatesAndFormats(): array + { + return [ + ['2010-01-01', 'Y-m-d'], + ['12-12-1955', 'm-d-Y'], + ['31-05-2030', 'd-m-Y'], + ['2010/01/01', 'Y/m/d'], + ['12/12/1955', 'm/d/Y'], + ['31/05/2030', 'd/m/Y'], + ['2010.01.01', 'Y.m.d'], + ['12.11.2010', 'm.d.Y'], + ['01.05.2030', 'd.m.Y'], + ['01.05/2030', 'd.m/Y'], + ['December 31, 1999', 'F d, Y'], + ]; + } } pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy