From 909e7d0a5a77604a4d047ee540643a930db6261a Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sat, 5 Apr 2025 11:43:26 +0200 Subject: [PATCH 1/6] [Serializer] Add PRESERVE_CONTEXT_TIMEZONE_KEY to DateTimeNormalizer Add PRESERVE_CONTEXT_TIMEZONE_KEY and adjust DateTime object during denormalization --- .../Normalizer/DateTimeNormalizer.php | 22 ++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index a136ec227a3ae..1d14a7e006bc2 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -25,11 +25,15 @@ final class DateTimeNormalizer implements NormalizerInterface, DenormalizerInter public const FORMAT_KEY = 'datetime_format'; public const TIMEZONE_KEY = 'datetime_timezone'; public const CAST_KEY = 'datetime_cast'; + /* if set to true during denormalization DateTime(Immutable) objects will always receive the timezone set in the context + and the tz from date strings and timestamps will be ignored */ + public const PRESERVE_CONTEXT_TIMEZONE_KEY = 'datetime_preserve_context_timezone'; private array $defaultContext = [ self::FORMAT_KEY => \DateTimeInterface::RFC3339, self::TIMEZONE_KEY => null, self::CAST_KEY => null, + self::PRESERVE_CONTEXT_TIMEZONE_KEY => false ]; private const SUPPORTED_TYPES = [ @@ -112,7 +116,7 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a if (null !== $dateTimeFormat) { if (false !== $object = $type::createFromFormat($dateTimeFormat, $data, $timezone)) { - return $object; + return $this->preserveContextTimezone($object, $context); } $dateTimeErrors = $type::getLastErrors(); @@ -124,11 +128,11 @@ public function denormalize(mixed $data, string $type, ?string $format = null, a if (null !== $defaultDateTimeFormat) { if (false !== $object = $type::createFromFormat($defaultDateTimeFormat, $data, $timezone)) { - return $object; + return $this->preserveContextTimezone($object, $context); } } - return new $type($data, $timezone); + return $this->preserveContextTimezone(new $type($data, $timezone), $context); } catch (NotNormalizableValueException $e) { throw $e; } catch (\Exception $e) { @@ -167,4 +171,16 @@ private function getTimezone(array $context): ?\DateTimeZone return $dateTimeZone instanceof \DateTimeZone ? $dateTimeZone : new \DateTimeZone($dateTimeZone); } + + private function preserveContextTimezone(\DateTimeInterface $object, array $context): \DateTimeInterface + { + $timezone = $this->getTimezone($context); + $preserveTimezone = $context[self::PRESERVE_CONTEXT_TIMEZONE_KEY] ?? $this->defaultContext[self::PRESERVE_CONTEXT_TIMEZONE_KEY] === true; + + if (null === $timezone || false === $preserveTimezone) { + return $object; + } + + return $object->setTimezone($timezone); + } } From e5f38c6615d34607b1e38c69ec61827d8a12f35a Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sat, 5 Apr 2025 11:44:55 +0200 Subject: [PATCH 2/6] [Serializer] Add PRESERVE_CONTEXT_TIMEZONE_KEY to DateTimeNormalizer Add test coverage --- .../Normalizer/DateTimeNormalizerTest.php | 53 +++++++++++++++++++ 1 file changed, 53 insertions(+) diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php index 81219652b3ef1..b2c563f17920f 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php @@ -308,6 +308,59 @@ public static function denormalizeUsingTimezonePassedInContextProvider() ]; } + public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInConstructor(): void + { + $normalizer = new DateTimeNormalizer( + [ + DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone('Japan'), + DateTimeNormalizer::FORMAT_KEY => 'Y-m-d\\TH:i:sO', + DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY => true, + ] + ); + $actual = $normalizer->denormalize('2016-12-01T12:34:56+0000', \DateTimeInterface::class); + $this->assertEquals(new \DateTimeZone('Japan'), $actual->getTimezone()); + } + + public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInContext(): void + { + $actual = $this->normalizer->denormalize( + '2016-12-01T12:34:56+0000', + \DateTimeInterface::class, + null, + [ + DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone('Japan'), + DateTimeNormalizer::FORMAT_KEY => 'Y-m-d\\TH:i:sO', + DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY => true, + ] + ); + $this->assertEquals(new \DateTimeZone('Japan'), $actual->getTimezone()); + } + + public function testDenormalizeUsingPreserveContextTimezoneWithoutFormat(): void + { + $actual = $this->normalizer->denormalize( + '2016-12-01T12:34:56+0000', + \DateTimeInterface::class, + null, + [ + DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone('Japan'), + DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY => true, + ] + ); + $this->assertEquals(new \DateTimeZone('Japan'), $actual->getTimezone()); + } + + public function testDenormalizeUsingPreserveContextShouldBeIgnoredWithoutTimezoneInContext(): void + { + $actual = $this->normalizer->denormalize( + '2016-12-01T12:34:56+0000', + \DateTimeInterface::class, + null, + [DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY => true] + ); + $this->assertEquals(new \DateTimeZone('+00:00'), $actual->getTimezone()); + } + public function testDenormalizeInvalidDataThrowsException() { $this->expectException(UnexpectedValueException::class); From d390d613d0bfcec49e7c08853dfff70ad35d7c73 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sat, 5 Apr 2025 11:49:04 +0200 Subject: [PATCH 3/6] [Serializer] Add PRESERVE_CONTEXT_TIMEZONE_KEY to DateTimeNormalizer Update changelog.md --- src/Symfony/Component/Serializer/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Symfony/Component/Serializer/CHANGELOG.md b/src/Symfony/Component/Serializer/CHANGELOG.md index 1b5c95cd39443..3c51182c504d1 100644 --- a/src/Symfony/Component/Serializer/CHANGELOG.md +++ b/src/Symfony/Component/Serializer/CHANGELOG.md @@ -4,6 +4,7 @@ CHANGELOG 7.3 --- + * Add `PRESERVE_CONTEXT_TIMEZONE_KEY` to `DateTimeNormalizer` to preserve the context timezone * Deprecate the `CompiledClassMetadataFactory` and `CompiledClassMetadataCacheWarmer` classes * Register `NormalizerInterface` and `DenormalizerInterface` aliases for named serializers * Add `NumberNormalizer` to normalize `BcMath\Number` and `GMP` as `string` From 573787891bb8b5693e049b8752a17fb85dc8ffc6 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Sat, 5 Apr 2025 12:09:51 +0200 Subject: [PATCH 4/6] [Serializer] Add PRESERVE_CONTEXT_TIMEZONE_KEY to DateTimeNormalizer Updated codequality failures --- .../Serializer/Normalizer/DateTimeNormalizer.php | 2 +- .../Tests/Normalizer/DateTimeNormalizerTest.php | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index 1d14a7e006bc2..a06c564b31f7f 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -172,7 +172,7 @@ private function getTimezone(array $context): ?\DateTimeZone return $dateTimeZone instanceof \DateTimeZone ? $dateTimeZone : new \DateTimeZone($dateTimeZone); } - private function preserveContextTimezone(\DateTimeInterface $object, array $context): \DateTimeInterface + private function preserveContextTimezone(\DateTime|\DateTimeImmutable $object, array $context): \DateTime|\DateTimeImmutable { $timezone = $this->getTimezone($context); $preserveTimezone = $context[self::PRESERVE_CONTEXT_TIMEZONE_KEY] ?? $this->defaultContext[self::PRESERVE_CONTEXT_TIMEZONE_KEY] === true; diff --git a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php index b2c563f17920f..f5094c453bcca 100644 --- a/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php +++ b/src/Symfony/Component/Serializer/Tests/Normalizer/DateTimeNormalizerTest.php @@ -308,7 +308,7 @@ public static function denormalizeUsingTimezonePassedInContextProvider() ]; } - public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInConstructor(): void + public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInConstructor() { $normalizer = new DateTimeNormalizer( [ @@ -321,7 +321,7 @@ public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInCons $this->assertEquals(new \DateTimeZone('Japan'), $actual->getTimezone()); } - public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInContext(): void + public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInContext() { $actual = $this->normalizer->denormalize( '2016-12-01T12:34:56+0000', @@ -336,7 +336,7 @@ public function testDenormalizeUsingPreserveContextTimezoneAndFormatPassedInCont $this->assertEquals(new \DateTimeZone('Japan'), $actual->getTimezone()); } - public function testDenormalizeUsingPreserveContextTimezoneWithoutFormat(): void + public function testDenormalizeUsingPreserveContextTimezoneWithoutFormat() { $actual = $this->normalizer->denormalize( '2016-12-01T12:34:56+0000', @@ -350,7 +350,7 @@ public function testDenormalizeUsingPreserveContextTimezoneWithoutFormat(): void $this->assertEquals(new \DateTimeZone('Japan'), $actual->getTimezone()); } - public function testDenormalizeUsingPreserveContextShouldBeIgnoredWithoutTimezoneInContext(): void + public function testDenormalizeUsingPreserveContextShouldBeIgnoredWithoutTimezoneInContext() { $actual = $this->normalizer->denormalize( '2016-12-01T12:34:56+0000', From 5f2bf53f8c724c34dc39e83e66726353e9e73857 Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Tue, 15 Apr 2025 14:03:46 +0200 Subject: [PATCH 5/6] [Serializer] Add PRESERVE_CONTEXT_TIMEZONE_KEY to DateTimeNormalizer Fix review remarks --- .../Component/Serializer/Normalizer/DateTimeNormalizer.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php index a06c564b31f7f..d28687dfb9126 100644 --- a/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php +++ b/src/Symfony/Component/Serializer/Normalizer/DateTimeNormalizer.php @@ -175,9 +175,9 @@ private function getTimezone(array $context): ?\DateTimeZone private function preserveContextTimezone(\DateTime|\DateTimeImmutable $object, array $context): \DateTime|\DateTimeImmutable { $timezone = $this->getTimezone($context); - $preserveTimezone = $context[self::PRESERVE_CONTEXT_TIMEZONE_KEY] ?? $this->defaultContext[self::PRESERVE_CONTEXT_TIMEZONE_KEY] === true; + $preserveTimezone = $context[self::PRESERVE_CONTEXT_TIMEZONE_KEY] ?? $this->defaultContext[self::PRESERVE_CONTEXT_TIMEZONE_KEY]; - if (null === $timezone || false === $preserveTimezone) { + if (null === $timezone || !$preserveTimezone) { return $object; } From 78fee13c3dca439831939e075a2d7dd97cb98c6d Mon Sep 17 00:00:00 2001 From: Frank Dekker Date: Tue, 15 Apr 2025 14:19:18 +0200 Subject: [PATCH 6/6] [Serializer] Add PRESERVE_CONTEXT_TIMEZONE_KEY to DateTimeNormalizer Add `withPreserveContextTimezone` to `DateTimeNormalizerContextBuilder` --- .../Normalizer/DateTimeNormalizerContextBuilder.php | 9 +++++++++ .../Normalizer/DateTimeNormalizerContextBuilderTest.php | 3 +++ 2 files changed, 12 insertions(+) diff --git a/src/Symfony/Component/Serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php b/src/Symfony/Component/Serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php index de83b1245455e..53a6dffcdf637 100644 --- a/src/Symfony/Component/Serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php +++ b/src/Symfony/Component/Serializer/Context/Normalizer/DateTimeNormalizerContextBuilder.php @@ -69,4 +69,13 @@ public function withCast(?string $cast): static { return $this->with(DateTimeNormalizer::CAST_KEY, $cast); } + + /** + * Configures if the timezone should be used from the context and ignore any timezone + * defined in date strings. + */ + public function withPreserveContextTimezone(?bool $preserveContextTimezone): static + { + return $this->with(DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY, $preserveContextTimezone); + } } diff --git a/src/Symfony/Component/Serializer/Tests/Context/Normalizer/DateTimeNormalizerContextBuilderTest.php b/src/Symfony/Component/Serializer/Tests/Context/Normalizer/DateTimeNormalizerContextBuilderTest.php index ac4badc19486b..feb1f4163004e 100644 --- a/src/Symfony/Component/Serializer/Tests/Context/Normalizer/DateTimeNormalizerContextBuilderTest.php +++ b/src/Symfony/Component/Serializer/Tests/Context/Normalizer/DateTimeNormalizerContextBuilderTest.php @@ -39,6 +39,7 @@ public function testWithers(array $values) ->withFormat($values[DateTimeNormalizer::FORMAT_KEY]) ->withTimezone($values[DateTimeNormalizer::TIMEZONE_KEY]) ->withCast($values[DateTimeNormalizer::CAST_KEY]) + ->withPreserveContextTimezone($values[DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY]) ->toArray(); $this->assertEquals($values, $context); @@ -53,12 +54,14 @@ public static function withersDataProvider(): iterable DateTimeNormalizer::FORMAT_KEY => 'format', DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone('GMT'), DateTimeNormalizer::CAST_KEY => 'int', + DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY => true, ]]; yield 'With null values' => [[ DateTimeNormalizer::FORMAT_KEY => null, DateTimeNormalizer::TIMEZONE_KEY => null, DateTimeNormalizer::CAST_KEY => null, + DateTimeNormalizer::PRESERVE_CONTEXT_TIMEZONE_KEY => null, ]]; } 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