diff --git a/core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php b/core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php index de8143bc56..6367762c8c 100644 --- a/core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php +++ b/core/modules/serialization/src/Normalizer/DateTimeIso8601Normalizer.php @@ -50,13 +50,19 @@ public function normalize($datetime, $format = NULL, array $context = []) { */ public function denormalize($data, $class, $format = NULL, array $context = []) { $date = parent::denormalize($data, $class, $format, $context); - // For consistency, we set the time to 12:00:00 UTC for date-only fields. + // Extract the year, month, and day from the object. + $ymd = $date->format('Y-m-d'); + // Rebuild the date object using the extracted year, month, and day, but + // for consistency set the time to 12:00:00 UTC upon creation for date-only + // fields. Rebuilding, instead of using the object methods, is done to + // avoid the initial date object picking up the local time and time zone + // from an input value with a missing or partial time string, and then + // rolling over to a different day when changing the object to UTC. // @see \Drupal\Component\Datetime\DateTimePlus::setDefaultDateTime() // @see \Drupal\datetime\Plugin\views\filter\Date::getOffset() // @see \Drupal\datetime\DateTimeComputed::getValue() - $date->setTimezone(new \DateTimeZone('UTC')); - $date->setTime(12, 0, 0); - return $date; + // @see http://php.net/manual/en/datetime.createfromformat.php + return \DateTime::createFromFormat('Y-m-d\TH:i:s O', $ymd . 'T12:00:00 UTC'); } } diff --git a/core/modules/serialization/tests/src/Unit/Normalizer/DateTimeIso8601NormalizerTest.php b/core/modules/serialization/tests/src/Unit/Normalizer/DateTimeIso8601NormalizerTest.php index c269ce9c7b..f49a47e8fb 100644 --- a/core/modules/serialization/tests/src/Unit/Normalizer/DateTimeIso8601NormalizerTest.php +++ b/core/modules/serialization/tests/src/Unit/Normalizer/DateTimeIso8601NormalizerTest.php @@ -161,9 +161,10 @@ public function testDenormalizeValidFormats($value, $expected) { $normalized = ['value' => $value]; $denormalized = $this->normalizer->denormalize($normalized, DateTimeIso8601::class, NULL, []); - $this->assertEquals($expected->format(\DateTime::RFC3339), $denormalized->format(\DateTime::RFC3339)); + $this->assertInstanceOf(\DateTime::class, $denormalized); $this->assertEquals('UTC', $denormalized->getTimezone()->getName()); $this->assertEquals('12:00:00', $denormalized->format('H:i:s')); + $this->assertEquals($expected->format(\DateTime::RFC3339), $denormalized->format(\DateTime::RFC3339)); } /**