[Serializer] Support specifying format for DateTimeNormalizer::denormalize
This commit is contained in:
parent
69e86547d4
commit
ff2392423b
@ -68,6 +68,26 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
|
|||||||
*/
|
*/
|
||||||
public function denormalize($data, $class, $format = null, array $context = array())
|
public function denormalize($data, $class, $format = null, array $context = array())
|
||||||
{
|
{
|
||||||
|
$dateTimeFormat = isset($context[self::FORMAT_KEY]) ? $context[self::FORMAT_KEY] : null;
|
||||||
|
|
||||||
|
if (null !== $dateTimeFormat) {
|
||||||
|
$object = \DateTime::class === $class ? \DateTime::createFromFormat($dateTimeFormat, $data) : \DateTimeImmutable::createFromFormat($dateTimeFormat, $data);
|
||||||
|
|
||||||
|
if (false !== $object) {
|
||||||
|
return $object;
|
||||||
|
}
|
||||||
|
|
||||||
|
$dateTimeErrors = \DateTime::class === $class ? \DateTime::getLastErrors() : \DateTimeImmutable::getLastErrors();
|
||||||
|
|
||||||
|
throw new UnexpectedValueException(sprintf(
|
||||||
|
'Parsing datetime string "%s" using format "%s" resulted in %d errors:'."\n".'%s',
|
||||||
|
$data,
|
||||||
|
$dateTimeFormat,
|
||||||
|
$dateTimeErrors['error_count'],
|
||||||
|
implode("\n", $this->formatDateTimeErrors($dateTimeErrors['errors']))
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
return \DateTime::class === $class ? new \DateTime($data) : new \DateTimeImmutable($data);
|
return \DateTime::class === $class ? new \DateTime($data) : new \DateTimeImmutable($data);
|
||||||
} catch (\Exception $e) {
|
} catch (\Exception $e) {
|
||||||
@ -88,4 +108,22 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
|
|||||||
|
|
||||||
return isset($supportedTypes[$type]);
|
return isset($supportedTypes[$type]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Formats datetime errors.
|
||||||
|
*
|
||||||
|
* @param array $errors
|
||||||
|
*
|
||||||
|
* @return string[]
|
||||||
|
*/
|
||||||
|
private function formatDateTimeErrors(array $errors)
|
||||||
|
{
|
||||||
|
$formattedErrors = array();
|
||||||
|
|
||||||
|
foreach ($errors as $pos => $message) {
|
||||||
|
$formattedErrors[] = sprintf('at position %d: %s', $pos, $message);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $formattedErrors;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ class DateTimeNormalizerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->normalizer = new DateTimeNormalizer();
|
$this->normalizer = new DateTimeNormalizer();
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportNormalization()
|
public function testSupportsNormalization()
|
||||||
{
|
{
|
||||||
$this->assertTrue($this->normalizer->supportsNormalization(new \DateTime()));
|
$this->assertTrue($this->normalizer->supportsNormalization(new \DateTime()));
|
||||||
$this->assertTrue($this->normalizer->supportsNormalization(new \DateTimeImmutable()));
|
$this->assertTrue($this->normalizer->supportsNormalization(new \DateTimeImmutable()));
|
||||||
@ -41,12 +41,12 @@ class DateTimeNormalizerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals('2016-01-01T00:00:00+00:00', $this->normalizer->normalize(new \DateTimeImmutable('2016/01/01', new \DateTimeZone('UTC'))));
|
$this->assertEquals('2016-01-01T00:00:00+00:00', $this->normalizer->normalize(new \DateTimeImmutable('2016/01/01', new \DateTimeZone('UTC'))));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testContextFormat()
|
public function testNormalizeUsingFormatPassedInContext()
|
||||||
{
|
{
|
||||||
$this->assertEquals('2016', $this->normalizer->normalize(new \DateTime('2016/01/01'), null, array(DateTimeNormalizer::FORMAT_KEY => 'Y')));
|
$this->assertEquals('2016', $this->normalizer->normalize(new \DateTime('2016/01/01'), null, array(DateTimeNormalizer::FORMAT_KEY => 'Y')));
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testConstructorFormat()
|
public function testNormalizeUsingFormatPassedInConstructor()
|
||||||
{
|
{
|
||||||
$this->assertEquals('16', (new DateTimeNormalizer('y'))->normalize(new \DateTime('2016/01/01', new \DateTimeZone('UTC'))));
|
$this->assertEquals('16', (new DateTimeNormalizer('y'))->normalize(new \DateTime('2016/01/01', new \DateTimeZone('UTC'))));
|
||||||
}
|
}
|
||||||
@ -55,12 +55,12 @@ class DateTimeNormalizerTest extends \PHPUnit_Framework_TestCase
|
|||||||
* @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException
|
* @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException
|
||||||
* @expectedExceptionMessage The object must implement the "\DateTimeInterface".
|
* @expectedExceptionMessage The object must implement the "\DateTimeInterface".
|
||||||
*/
|
*/
|
||||||
public function testInvalidDataThrowException()
|
public function testNormalizeInvalidObjectThrowsException()
|
||||||
{
|
{
|
||||||
$this->normalizer->normalize(new \stdClass());
|
$this->normalizer->normalize(new \stdClass());
|
||||||
}
|
}
|
||||||
|
|
||||||
public function testSupportDenormalization()
|
public function testSupportsDenormalization()
|
||||||
{
|
{
|
||||||
$this->assertTrue($this->normalizer->supportsDenormalization('2016-01-01T00:00:00+00:00', \DateTimeInterface::class));
|
$this->assertTrue($this->normalizer->supportsDenormalization('2016-01-01T00:00:00+00:00', \DateTimeInterface::class));
|
||||||
$this->assertTrue($this->normalizer->supportsDenormalization('2016-01-01T00:00:00+00:00', \DateTime::class));
|
$this->assertTrue($this->normalizer->supportsDenormalization('2016-01-01T00:00:00+00:00', \DateTime::class));
|
||||||
@ -75,11 +75,26 @@ class DateTimeNormalizerTest extends \PHPUnit_Framework_TestCase
|
|||||||
$this->assertEquals(new \DateTime('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', \DateTime::class));
|
$this->assertEquals(new \DateTime('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016-01-01T00:00:00+00:00', \DateTime::class));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function testDenormalizeUsingFormatPassedInContext()
|
||||||
|
{
|
||||||
|
$this->assertEquals(new \DateTimeImmutable('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016.01.01', \DateTimeInterface::class, null, array(DateTimeNormalizer::FORMAT_KEY => 'Y.m.d|')));
|
||||||
|
$this->assertEquals(new \DateTimeImmutable('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016.01.01', \DateTimeImmutable::class, null, array(DateTimeNormalizer::FORMAT_KEY => 'Y.m.d|')));
|
||||||
|
$this->assertEquals(new \DateTime('2016/01/01', new \DateTimeZone('UTC')), $this->normalizer->denormalize('2016.01.01', \DateTime::class, null, array(DateTimeNormalizer::FORMAT_KEY => 'Y.m.d|')));
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
|
* @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
|
||||||
*/
|
*/
|
||||||
public function testInvalidDateThrowException()
|
public function testDenormalizeInvalidDataThrowsException()
|
||||||
{
|
{
|
||||||
$this->normalizer->denormalize('invalid date', \DateTimeInterface::class);
|
$this->normalizer->denormalize('invalid date', \DateTimeInterface::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @expectedException \Symfony\Component\Serializer\Exception\UnexpectedValueException
|
||||||
|
*/
|
||||||
|
public function testDenormalizeFormatMismatchThrowsException()
|
||||||
|
{
|
||||||
|
$this->normalizer->denormalize('2016-01-01T00:00:00+00:00', \DateTimeInterface::class, null, array(DateTimeNormalizer::FORMAT_KEY => 'Y-m-d|'));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user