2016-01-17 12:10:27 +00:00
< ? php
/*
* This file is part of the Symfony package .
*
* ( c ) Fabien Potencier < fabien @ symfony . com >
*
* For the full copyright and license information , please view the LICENSE
* file that was distributed with this source code .
*/
namespace Symfony\Component\Serializer\Tests\Normalizer ;
2017-02-20 13:34:33 +00:00
use PHPUnit\Framework\TestCase ;
2016-01-17 12:10:27 +00:00
use Symfony\Component\Serializer\Normalizer\DateTimeNormalizer ;
/**
* @ author Kévin Dunglas < dunglas @ gmail . com >
*/
2017-02-20 13:34:33 +00:00
class DateTimeNormalizerTest extends TestCase
2016-01-17 12:10:27 +00:00
{
/**
* @ var DateTimeNormalizer
*/
private $normalizer ;
2019-08-08 10:17:10 +01:00
protected function setUp () : void
2016-01-17 12:10:27 +00:00
{
$this -> normalizer = new DateTimeNormalizer ();
}
2016-10-14 09:04:25 +01:00
public function testSupportsNormalization ()
2016-01-17 12:10:27 +00:00
{
$this -> assertTrue ( $this -> normalizer -> supportsNormalization ( new \DateTime ()));
$this -> assertTrue ( $this -> normalizer -> supportsNormalization ( new \DateTimeImmutable ()));
$this -> assertFalse ( $this -> normalizer -> supportsNormalization ( new \stdClass ()));
}
public function testNormalize ()
{
2016-02-04 14:04:32 +00:00
$this -> assertEquals ( '2016-01-01T00:00:00+00:00' , $this -> normalizer -> normalize ( new \DateTime ( '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' ))));
2016-01-17 12:10:27 +00:00
}
2016-10-14 09:04:25 +01:00
public function testNormalizeUsingFormatPassedInContext ()
2016-01-17 12:10:27 +00:00
{
2019-01-16 09:39:14 +00:00
$this -> assertEquals ( '2016' , $this -> normalizer -> normalize ( new \DateTime ( '2016/01/01' ), null , [ DateTimeNormalizer :: FORMAT_KEY => 'Y' ]));
2016-01-17 12:10:27 +00:00
}
2016-10-14 09:04:25 +01:00
public function testNormalizeUsingFormatPassedInConstructor ()
2016-01-17 12:10:27 +00:00
{
2018-10-03 16:09:15 +01:00
$this -> doTestNormalizeUsingFormatPassedInConstructor ();
}
public function testLegacyNormalizeUsingFormatPassedInConstructor ()
{
$this -> doTestNormalizeUsingFormatPassedInConstructor ( true );
}
private function doTestNormalizeUsingFormatPassedInConstructor ( bool $legacy = false )
{
2019-01-16 20:35:37 +00:00
$normalizer = $legacy ? new DateTimeNormalizer ( 'y' ) : new DateTimeNormalizer ([ DateTimeNormalizer :: FORMAT_KEY => 'y' ]);
2018-10-03 16:09:15 +01:00
$this -> assertEquals ( '16' , $normalizer -> normalize ( new \DateTime ( '2016/01/01' , new \DateTimeZone ( 'UTC' ))));
2016-01-17 12:10:27 +00:00
}
2017-04-15 12:48:33 +01:00
public function testNormalizeUsingTimeZonePassedInConstructor ()
{
2018-10-03 16:09:15 +01:00
$this -> doTestNormalizeUsingTimeZonePassedInConstructor ();
}
public function testLegacyNormalizeUsingTimeZonePassedInConstructor ()
{
$this -> doTestNormalizeUsingTimeZonePassedInConstructor ( true );
}
private function doTestNormalizeUsingTimeZonePassedInConstructor ( bool $legacy = false )
{
if ( $legacy ) {
$normalizer = new DateTimeNormalizer ( \DateTime :: RFC3339 , new \DateTimeZone ( 'Japan' ));
} else {
2019-01-16 20:35:37 +00:00
$normalizer = new DateTimeNormalizer ([ DateTimeNormalizer :: TIMEZONE_KEY => new \DateTimeZone ( 'Japan' )]);
2018-10-03 16:09:15 +01:00
}
2017-04-15 12:48:33 +01:00
$this -> assertSame ( '2016-12-01T00:00:00+09:00' , $normalizer -> normalize ( new \DateTime ( '2016/12/01' , new \DateTimeZone ( 'Japan' ))));
$this -> assertSame ( '2016-12-01T09:00:00+09:00' , $normalizer -> normalize ( new \DateTime ( '2016/12/01' , new \DateTimeZone ( 'UTC' ))));
}
/**
* @ dataProvider normalizeUsingTimeZonePassedInContextProvider
*/
public function testNormalizeUsingTimeZonePassedInContext ( $expected , $input , $timezone )
{
2019-01-16 09:39:14 +00:00
$this -> assertSame ( $expected , $this -> normalizer -> normalize ( $input , null , [
2017-04-15 12:48:33 +01:00
DateTimeNormalizer :: TIMEZONE_KEY => $timezone ,
2019-01-16 09:39:14 +00:00
]));
2017-04-15 12:48:33 +01:00
}
public function normalizeUsingTimeZonePassedInContextProvider ()
{
2019-01-16 09:39:14 +00:00
yield [ '2016-12-01T00:00:00+00:00' , new \DateTime ( '2016/12/01' , new \DateTimeZone ( 'UTC' )), null ];
yield [ '2016-12-01T00:00:00+09:00' , new \DateTime ( '2016/12/01' , new \DateTimeZone ( 'Japan' )), new \DateTimeZone ( 'Japan' )];
yield [ '2016-12-01T09:00:00+09:00' , new \DateTime ( '2016/12/01' , new \DateTimeZone ( 'UTC' )), new \DateTimeZone ( 'Japan' )];
yield [ '2016-12-01T09:00:00+09:00' , new \DateTimeImmutable ( '2016/12/01' , new \DateTimeZone ( 'UTC' )), new \DateTimeZone ( 'Japan' )];
2017-04-15 12:48:33 +01:00
}
2018-12-01 18:23:29 +00:00
/**
* @ dataProvider normalizeUsingTimeZonePassedInContextAndExpectedFormatWithMicrosecondsProvider
*/
public function testNormalizeUsingTimeZonePassedInContextAndFormattedWithMicroseconds ( $expected , $expectedFormat , $input , $timezone )
{
$this -> assertSame (
$expected ,
$this -> normalizer -> normalize (
$input ,
null ,
2019-01-16 09:39:14 +00:00
[
2018-12-01 18:23:29 +00:00
DateTimeNormalizer :: TIMEZONE_KEY => $timezone ,
DateTimeNormalizer :: FORMAT_KEY => $expectedFormat ,
2019-01-16 09:39:14 +00:00
]
2018-12-01 18:23:29 +00:00
)
);
}
public function normalizeUsingTimeZonePassedInContextAndExpectedFormatWithMicrosecondsProvider ()
{
2019-01-16 09:39:14 +00:00
yield [
2018-12-01 18:23:29 +00:00
'2018-12-01T18:03:06.067634' ,
'Y-m-d\TH:i:s.u' ,
\DateTime :: createFromFormat (
'Y-m-d\TH:i:s.u' ,
'2018-12-01T18:03:06.067634' ,
new \DateTimeZone ( 'UTC' )
),
null ,
2019-01-16 09:39:14 +00:00
];
2018-12-01 18:23:29 +00:00
2019-01-16 09:39:14 +00:00
yield [
2018-12-01 18:23:29 +00:00
'2018-12-01T18:03:06.067634' ,
'Y-m-d\TH:i:s.u' ,
\DateTime :: createFromFormat (
'Y-m-d\TH:i:s.u' ,
'2018-12-01T18:03:06.067634' ,
new \DateTimeZone ( 'UTC' )
),
new \DateTimeZone ( 'UTC' ),
2019-01-16 09:39:14 +00:00
];
2018-12-01 18:23:29 +00:00
2019-01-16 09:39:14 +00:00
yield [
2018-12-01 18:23:29 +00:00
'2018-12-01T19:03:06.067634+01:00' ,
'Y-m-d\TH:i:s.uP' ,
\DateTimeImmutable :: createFromFormat (
'Y-m-d\TH:i:s.u' ,
'2018-12-01T18:03:06.067634' ,
new \DateTimeZone ( 'UTC' )
),
new \DateTimeZone ( 'Europe/Rome' ),
2019-01-16 09:39:14 +00:00
];
2018-12-01 18:23:29 +00:00
2019-01-16 09:39:14 +00:00
yield [
2018-12-01 18:23:29 +00:00
'2018-12-01T20:03:06.067634+02:00' ,
'Y-m-d\TH:i:s.uP' ,
\DateTime :: createFromFormat (
'Y-m-d\TH:i:s.u' ,
'2018-12-01T18:03:06.067634' ,
new \DateTimeZone ( 'UTC' )
),
new \DateTimeZone ( 'Europe/Kiev' ),
2019-01-16 09:39:14 +00:00
];
2018-12-01 18:23:29 +00:00
2019-01-16 09:39:14 +00:00
yield [
2018-12-07 15:51:05 +00:00
'2018-12-01T19:03:06.067634' ,
2018-12-01 18:23:29 +00:00
'Y-m-d\TH:i:s.u' ,
\DateTime :: createFromFormat (
'Y-m-d\TH:i:s.u' ,
'2018-12-01T18:03:06.067634' ,
new \DateTimeZone ( 'UTC' )
),
2018-12-07 15:51:05 +00:00
new \DateTimeZone ( 'Europe/Berlin' ),
2019-01-16 09:39:14 +00:00
];
2018-12-01 18:23:29 +00:00
}
2016-10-14 09:04:25 +01:00
public function testNormalizeInvalidObjectThrowsException ()
2016-01-17 12:10:27 +00:00
{
2019-08-01 23:48:42 +01:00
$this -> expectException ( 'Symfony\Component\Serializer\Exception\InvalidArgumentException' );
$this -> expectExceptionMessage ( 'The object must implement the "\DateTimeInterface".' );
2016-01-17 12:10:27 +00:00
$this -> normalizer -> normalize ( new \stdClass ());
}
2016-10-14 09:04:25 +01:00
public function testSupportsDenormalization ()
2016-01-17 12:10:27 +00:00
{
$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' , \DateTimeImmutable :: class ));
$this -> assertFalse ( $this -> normalizer -> supportsDenormalization ( 'foo' , 'Bar' ));
}
public function testDenormalize ()
{
2016-02-04 14:04:32 +00:00
$this -> assertEquals ( new \DateTimeImmutable ( '2016/01/01' , new \DateTimeZone ( 'UTC' )), $this -> normalizer -> denormalize ( '2016-01-01T00:00:00+00:00' , \DateTimeInterface :: class ));
$this -> assertEquals ( new \DateTimeImmutable ( '2016/01/01' , new \DateTimeZone ( 'UTC' )), $this -> normalizer -> denormalize ( '2016-01-01T00:00:00+00:00' , \DateTimeImmutable :: class ));
$this -> assertEquals ( new \DateTime ( '2016/01/01' , new \DateTimeZone ( 'UTC' )), $this -> normalizer -> denormalize ( '2016-01-01T00:00:00+00:00' , \DateTime :: class ));
2016-01-17 12:10:27 +00:00
}
2017-04-15 12:48:33 +01:00
public function testDenormalizeUsingTimezonePassedInConstructor ()
2018-10-03 16:09:15 +01:00
{
$this -> doTestDenormalizeUsingTimezonePassedInConstructor ();
}
public function testLegacyDenormalizeUsingTimezonePassedInConstructor ()
{
$this -> doTestDenormalizeUsingTimezonePassedInConstructor ( true );
}
private function doTestDenormalizeUsingTimezonePassedInConstructor ( bool $legacy = false )
2017-04-15 12:48:33 +01:00
{
$timezone = new \DateTimeZone ( 'Japan' );
$expected = new \DateTime ( '2016/12/01 17:35:00' , $timezone );
2019-01-16 20:35:37 +00:00
$normalizer = $legacy ? new DateTimeNormalizer ( null , $timezone ) : new DateTimeNormalizer ([ DateTimeNormalizer :: TIMEZONE_KEY => $timezone ]);
2017-04-15 12:48:33 +01:00
2019-01-16 09:39:14 +00:00
$this -> assertEquals ( $expected , $normalizer -> denormalize ( '2016.12.01 17:35:00' , \DateTime :: class , null , [
2017-04-15 12:48:33 +01:00
DateTimeNormalizer :: FORMAT_KEY => 'Y.m.d H:i:s' ,
2019-01-16 09:39:14 +00:00
]));
2017-04-15 12:48:33 +01:00
}
2016-10-14 09:04:25 +01:00
public function testDenormalizeUsingFormatPassedInContext ()
{
2019-01-16 09:39:14 +00:00
$this -> assertEquals ( new \DateTimeImmutable ( '2016/01/01' ), $this -> normalizer -> denormalize ( '2016.01.01' , \DateTimeInterface :: class , null , [ DateTimeNormalizer :: FORMAT_KEY => 'Y.m.d|' ]));
$this -> assertEquals ( new \DateTimeImmutable ( '2016/01/01' ), $this -> normalizer -> denormalize ( '2016.01.01' , \DateTimeImmutable :: class , null , [ DateTimeNormalizer :: FORMAT_KEY => 'Y.m.d|' ]));
$this -> assertEquals ( new \DateTime ( '2016/01/01' ), $this -> normalizer -> denormalize ( '2016.01.01' , \DateTime :: class , null , [ DateTimeNormalizer :: FORMAT_KEY => 'Y.m.d|' ]));
2016-10-14 09:04:25 +01:00
}
2017-04-15 12:48:33 +01:00
/**
* @ dataProvider denormalizeUsingTimezonePassedInContextProvider
*/
public function testDenormalizeUsingTimezonePassedInContext ( $input , $expected , $timezone , $format = null )
{
2019-01-16 09:39:14 +00:00
$actual = $this -> normalizer -> denormalize ( $input , \DateTimeInterface :: class , null , [
2017-04-15 12:48:33 +01:00
DateTimeNormalizer :: TIMEZONE_KEY => $timezone ,
DateTimeNormalizer :: FORMAT_KEY => $format ,
2019-01-16 09:39:14 +00:00
]);
2017-04-15 12:48:33 +01:00
$this -> assertEquals ( $expected , $actual );
}
public function denormalizeUsingTimezonePassedInContextProvider ()
{
2019-01-16 09:39:14 +00:00
yield 'with timezone' => [
2017-04-15 12:48:33 +01:00
'2016/12/01 17:35:00' ,
new \DateTimeImmutable ( '2016/12/01 17:35:00' , new \DateTimeZone ( 'Japan' )),
new \DateTimeZone ( 'Japan' ),
2019-01-16 09:39:14 +00:00
];
yield 'with timezone as string' => [
2017-04-15 12:48:33 +01:00
'2016/12/01 17:35:00' ,
new \DateTimeImmutable ( '2016/12/01 17:35:00' , new \DateTimeZone ( 'Japan' )),
'Japan' ,
2019-01-16 09:39:14 +00:00
];
yield 'with format without timezone information' => [
2017-04-15 12:48:33 +01:00
'2016.12.01 17:35:00' ,
new \DateTimeImmutable ( '2016/12/01 17:35:00' , new \DateTimeZone ( 'Japan' )),
new \DateTimeZone ( 'Japan' ),
'Y.m.d H:i:s' ,
2019-01-16 09:39:14 +00:00
];
yield 'ignored with format with timezone information' => [
2017-04-15 12:48:33 +01:00
'2016-12-01T17:35:00Z' ,
new \DateTimeImmutable ( '2016/12/01 17:35:00' , new \DateTimeZone ( 'UTC' )),
'Europe/Paris' ,
\DateTime :: RFC3339 ,
2019-01-16 09:39:14 +00:00
];
2017-04-15 12:48:33 +01:00
}
2016-10-14 09:04:25 +01:00
public function testDenormalizeInvalidDataThrowsException ()
2016-01-17 12:10:27 +00:00
{
2019-08-01 23:48:42 +01:00
$this -> expectException ( 'Symfony\Component\Serializer\Exception\UnexpectedValueException' );
2016-01-17 12:10:27 +00:00
$this -> normalizer -> denormalize ( 'invalid date' , \DateTimeInterface :: class );
}
2016-10-14 09:04:25 +01:00
2017-12-03 14:02:49 +00:00
public function testDenormalizeNullThrowsException ()
{
2019-08-01 23:48:42 +01:00
$this -> expectException ( 'Symfony\Component\Serializer\Exception\UnexpectedValueException' );
$this -> expectExceptionMessage ( 'The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.' );
2017-12-03 14:02:49 +00:00
$this -> normalizer -> denormalize ( null , \DateTimeInterface :: class );
}
public function testDenormalizeEmptyStringThrowsException ()
{
2019-08-01 23:48:42 +01:00
$this -> expectException ( 'Symfony\Component\Serializer\Exception\UnexpectedValueException' );
$this -> expectExceptionMessage ( 'The data is either an empty string or null, you should pass a string that can be parsed with the passed format or a valid DateTime string.' );
2017-12-03 14:02:49 +00:00
$this -> normalizer -> denormalize ( '' , \DateTimeInterface :: class );
}
2016-10-14 09:04:25 +01:00
public function testDenormalizeFormatMismatchThrowsException ()
{
2019-08-01 23:48:42 +01:00
$this -> expectException ( 'Symfony\Component\Serializer\Exception\UnexpectedValueException' );
2019-01-16 09:39:14 +00:00
$this -> normalizer -> denormalize ( '2016-01-01T00:00:00+00:00' , \DateTimeInterface :: class , null , [ DateTimeNormalizer :: FORMAT_KEY => 'Y-m-d|' ]);
2016-10-14 09:04:25 +01:00
}
2016-01-17 12:10:27 +00:00
}