[Serializer] Support specifying format for DateTimeNormalizer::denormalize

This commit is contained in:
Teoh Han Hui 2016-10-14 16:04:25 +08:00
parent 69e86547d4
commit ff2392423b
No known key found for this signature in database
GPG Key ID: 729783C96A30C9B8
2 changed files with 59 additions and 6 deletions

View File

@ -68,6 +68,26 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
*/
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 {
return \DateTime::class === $class ? new \DateTime($data) : new \DateTimeImmutable($data);
} catch (\Exception $e) {
@ -88,4 +108,22 @@ class DateTimeNormalizer implements NormalizerInterface, DenormalizerInterface
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;
}
}

View File

@ -28,7 +28,7 @@ class DateTimeNormalizerTest extends \PHPUnit_Framework_TestCase
$this->normalizer = new DateTimeNormalizer();
}
public function testSupportNormalization()
public function testSupportsNormalization()
{
$this->assertTrue($this->normalizer->supportsNormalization(new \DateTime()));
$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'))));
}
public function testContextFormat()
public function testNormalizeUsingFormatPassedInContext()
{
$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'))));
}
@ -55,12 +55,12 @@ class DateTimeNormalizerTest extends \PHPUnit_Framework_TestCase
* @expectedException \Symfony\Component\Serializer\Exception\InvalidArgumentException
* @expectedExceptionMessage The object must implement the "\DateTimeInterface".
*/
public function testInvalidDataThrowException()
public function testNormalizeInvalidObjectThrowsException()
{
$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', \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));
}
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
*/
public function testInvalidDateThrowException()
public function testDenormalizeInvalidDataThrowsException()
{
$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|'));
}
}