From 763ea05db5c7ab8b5297aeabc5616d3eb9bd6fc7 Mon Sep 17 00:00:00 2001 From: Edvin Hultberg Date: Tue, 5 Oct 2021 19:39:51 +0200 Subject: [PATCH] [Serializer] Respect default context in DateTimeNormalizer::denormalize fixes #29030 --- .../Normalizer/DateTimeNormalizer.php | 10 +++++++++ .../Normalizer/DateTimeNormalizerTest.php | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index f48745031e8b7..5fab3d8a55d6d 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -113,6 +113,16 @@ public function denormalize($data, $type, $format = null, array $context = []) throw new NotNormalizableValueException(sprintf('Parsing datetime string "%s" using format "%s" resulted in %d errors: ', $data, $dateTimeFormat, $dateTimeErrors['error_count'])."\n".implode("\n", $this->formatDateTimeErrors($dateTimeErrors['errors']))); } + $defaultDateTimeFormat = $this->defaultContext[self::FORMAT_KEY] ?? null; + + if (null !== $defaultDateTimeFormat) { + $object = \DateTime::class === $type ? \DateTime::createFromFormat($defaultDateTimeFormat, $data, $timezone) : \DateTimeImmutable::createFromFormat($defaultDateTimeFormat, $data, $timezone); + + if (false !== $object) { + return $object; + } + } + try { return \DateTime::class === $type ? new \DateTime($data, $timezone) : new \DateTimeImmutable($data, $timezone); } catch (\Exception $e) { diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php index 51fc17d85afea..ca740a4d7e89e 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php @@ -305,6 +305,28 @@ public function testDenormalizeDateTimeStringWithSpacesUsingFormatPassedInContex $this->normalizer->denormalize(' 2016.01.01 ', \DateTime::class, null, [DateTimeNormalizer::FORMAT_KEY => 'Y.m.d|']); } + public function testDenormalizeDateTimeStringWithDefaultContextFormat() + { + $format = 'd/m/Y'; + $string = '01/10/2018'; + + $normalizer = new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => $format]); + $denormalizedDate = $normalizer->denormalize($string, \DateTimeInterface::class); + + $this->assertSame('01/10/2018', $denormalizedDate->format($format)); + } + + public function testDenormalizeDateTimeStringWithDefaultContextAllowsErrorFormat() + { + $format = 'd/m/Y'; // the default format + $string = '2020-01-01'; // the value which is in the wrong format, but is accepted because of `new \DateTime` in DateTimeNormalizer::denormalize + + $normalizer = new DateTimeNormalizer([DateTimeNormalizer::FORMAT_KEY => $format]); + $denormalizedDate = $normalizer->denormalize($string, \DateTimeInterface::class); + + $this->assertSame('2020-01-01', $denormalizedDate->format('Y-m-d')); + } + public function testDenormalizeFormatMismatchThrowsException() { $this->expectException(UnexpectedValueException::class);