12
12
namespace Symfony \Component \Serializer \Tests \Normalizer ;
13
13
14
14
use PHPUnit \Framework \TestCase ;
15
+ use Symfony \Bridge \PhpUnit \ExpectDeprecationTrait ;
15
16
use Symfony \Component \Serializer \Exception \InvalidArgumentException ;
16
17
use Symfony \Component \Serializer \Exception \UnexpectedValueException ;
17
18
use Symfony \Component \Serializer \Normalizer \DateTimeNormalizer ;
21
22
*/
22
23
class DateTimeNormalizerTest extends TestCase
23
24
{
25
+ use ExpectDeprecationTrait;
26
+
24
27
private DateTimeNormalizer $ normalizer ;
25
28
26
29
protected function setUp (): void
27
30
{
28
- $ this ->normalizer = new DateTimeNormalizer ();
31
+ $ this ->normalizer = new DateTimeNormalizer ([
32
+ DateTimeNormalizer::TIMESTAMP_CAST_KEY => true ,
33
+ ]);
29
34
}
30
35
31
36
public function testSupportsNormalization ()
@@ -48,13 +53,13 @@ public function testNormalizeUsingFormatPassedInContext()
48
53
49
54
public function testNormalizeUsingFormatPassedInConstructor ()
50
55
{
51
- $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::FORMAT_KEY => 'y ' ]);
56
+ $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::FORMAT_KEY => 'y ' , DateTimeNormalizer:: TIMESTAMP_CAST_KEY => true ]);
52
57
$ this ->assertEquals ('16 ' , $ normalizer ->normalize (new \DateTimeImmutable ('2016/01/01 ' , new \DateTimeZone ('UTC ' ))));
53
58
}
54
59
55
60
public function testNormalizeUsingTimeZonePassedInConstructor ()
56
61
{
57
- $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone ('Japan ' )]);
62
+ $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::TIMEZONE_KEY => new \DateTimeZone ('Japan ' ), DateTimeNormalizer:: TIMESTAMP_CAST_KEY => true ]);
58
63
59
64
$ this ->assertSame ('2016-12-01T00:00:00+09:00 ' , $ normalizer ->normalize (new \DateTimeImmutable ('2016/12/01 ' , new \DateTimeZone ('Japan ' ))));
60
65
$ this ->assertSame ('2016-12-01T09:00:00+09:00 ' , $ normalizer ->normalize (new \DateTimeImmutable ('2016/12/01 ' , new \DateTimeZone ('UTC ' ))));
@@ -154,6 +159,60 @@ public static function normalizeUsingTimeZonePassedInContextAndExpectedFormatWit
154
159
];
155
160
}
156
161
162
+ /**
163
+ * @dataProvider provideNormalizeUsingTimestampCastCases
164
+ */
165
+ public function testNormalizeUsingTimestampCast (\DateTimeInterface $ date , string $ format , int |float $ expectedResult )
166
+ {
167
+ self ::assertSame ($ expectedResult , $ this ->normalizer ->normalize ($ date , null , [
168
+ DateTimeNormalizer::TIMESTAMP_CAST_KEY => true ,
169
+ DateTimeNormalizer::FORMAT_KEY => $ format ,
170
+ ]));
171
+ }
172
+
173
+ /**
174
+ * @dataProvider provideNormalizeUsingTimestampCastCases
175
+ */
176
+ public function testNormalizeUsingTimestampCastFromDefaultContext (\DateTimeInterface $ date , string $ format , int |float $ expectedResult )
177
+ {
178
+ $ normalizer = new DateTimeNormalizer ([
179
+ DateTimeNormalizer::TIMESTAMP_CAST_KEY => true ,
180
+ DateTimeNormalizer::FORMAT_KEY => $ format ,
181
+ ]);
182
+
183
+ self ::assertSame ($ expectedResult , $ normalizer ->normalize ($ date ));
184
+ }
185
+
186
+ /**
187
+ * @return iterable<array{0: \DateTimeInterface, 1: non-empty-string, 2: int|float}>
188
+ */
189
+ public static function provideNormalizeUsingTimestampCastCases (): iterable
190
+ {
191
+ yield [
192
+ new \DateTimeImmutable ('2016-01-01T00:00:00+00:00 ' ),
193
+ 'U ' ,
194
+ 1451606400 ,
195
+ ];
196
+
197
+ yield [
198
+ new \DateTimeImmutable ('2016-01-01T00:00:00.123456+00:00 ' ),
199
+ 'U.u ' ,
200
+ 1451606400.123456 ,
201
+ ];
202
+
203
+ yield [
204
+ new \DateTimeImmutable ('2016-01-01T00:00:00.123456+00:00 ' ),
205
+ 'Uv ' ,
206
+ 1451606400123 ,
207
+ ];
208
+
209
+ yield [
210
+ new \DateTimeImmutable ('2016-01-01T00:00:00.123456+00:00 ' ),
211
+ 'Uu ' ,
212
+ 1451606400123456 ,
213
+ ];
214
+ }
215
+
157
216
public function testNormalizeInvalidObjectThrowsException ()
158
217
{
159
218
$ this ->expectException (InvalidArgumentException::class);
@@ -183,7 +242,7 @@ public function testDenormalizeUsingTimezonePassedInConstructor()
183
242
{
184
243
$ timezone = new \DateTimeZone ('Japan ' );
185
244
$ expected = new \DateTimeImmutable ('2016/12/01 17:35:00 ' , $ timezone );
186
- $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::TIMEZONE_KEY => $ timezone ]);
245
+ $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::TIMEZONE_KEY => $ timezone, DateTimeNormalizer:: TIMESTAMP_CAST_KEY => true ]);
187
246
188
247
$ this ->assertEquals ($ expected , $ normalizer ->denormalize ('2016.12.01 17:35:00 ' , \DateTimeImmutable::class, null , [
189
248
DateTimeNormalizer::FORMAT_KEY => 'Y.m.d H:i:s ' ,
@@ -277,28 +336,58 @@ public function testDenormalizeDateTimeStringWithSpacesUsingFormatPassedInContex
277
336
$ this ->normalizer ->denormalize (' 2016.01.01 ' , \DateTime::class, null , [DateTimeNormalizer::FORMAT_KEY => 'Y.m.d| ' ]);
278
337
}
279
338
280
- public function testDenormalizeTimestampWithFormatInContext ()
339
+ /**
340
+ * @dataProvider provideDenormalizeTimestampCases
341
+ */
342
+ public function testDenormalizeTimestampWithFormatInContext (int |float $ data , string $ format , string $ expectedResult )
343
+ {
344
+ $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::TIMESTAMP_CAST_KEY => true ]);
345
+ $ denormalizedDate = $ normalizer ->denormalize ($ data , \DateTimeInterface::class, null , [DateTimeNormalizer::FORMAT_KEY => $ format ]);
346
+
347
+ $ this ->assertSame ($ expectedResult , $ denormalizedDate ->format ('Y-m-d H:i:s.u ' ));
348
+ }
349
+
350
+ /**
351
+ * @dataProvider provideDenormalizeTimestampCases
352
+ */
353
+ public function testDenormalizeTimestampWithFormatInDefaultContext (int |float $ data , string $ format , string $ expectedResult )
281
354
{
282
- $ normalizer = new DateTimeNormalizer ();
283
- $ denormalizedDate = $ normalizer ->denormalize (1698202249 , \DateTimeInterface::class, null , [DateTimeNormalizer:: FORMAT_KEY => ' U ' ] );
355
+ $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer:: FORMAT_KEY => $ format , DateTimeNormalizer:: TIMESTAMP_CAST_KEY => true ] );
356
+ $ denormalizedDate = $ normalizer ->denormalize ($ data , \DateTimeInterface::class);
284
357
285
- $ this ->assertSame (' 2023-10-25 02:50:49 ' , $ denormalizedDate ->format ('Y-m-d H:i:s ' ));
358
+ $ this ->assertSame ($ expectedResult , $ denormalizedDate ->format ('Y-m-d H:i:s.u ' ));
286
359
}
287
360
288
- public function testDenormalizeTimestampWithFormatInDefaultContext ()
361
+ /**
362
+ * @return iterable<array{0: int|float, 1: non-empty-string, 2: non-empty-string}>
363
+ */
364
+ public function provideDenormalizeTimestampCases (): iterable
289
365
{
290
- $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::FORMAT_KEY => 'U ' ]);
291
- $ denormalizedDate = $ normalizer ->denormalize (1698202249 , \DateTimeInterface::class);
366
+ yield [
367
+ 1698202249 ,
368
+ 'U ' ,
369
+ '2023-10-25 02:50:49.000000 ' ,
370
+ ];
292
371
293
- $ this ->assertSame ('2023-10-25 02:50:49 ' , $ denormalizedDate ->format ('Y-m-d H:i:s ' ));
372
+ yield [
373
+ 1698202249.666 ,
374
+ 'U.u ' ,
375
+ '2023-10-25 02:50:49.666000 ' ,
376
+ ];
377
+
378
+ yield [
379
+ 1698202249.123456 ,
380
+ 'U.u ' ,
381
+ '2023-10-25 02:50:49.123456 ' ,
382
+ ];
294
383
}
295
384
296
385
public function testDenormalizeDateTimeStringWithDefaultContextFormat ()
297
386
{
298
387
$ format = 'd/m/Y ' ;
299
388
$ string = '01/10/2018 ' ;
300
389
301
- $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::FORMAT_KEY => $ format ]);
390
+ $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::FORMAT_KEY => $ format, DateTimeNormalizer:: TIMESTAMP_CAST_KEY => true ]);
302
391
$ denormalizedDate = $ normalizer ->denormalize ($ string , \DateTimeInterface::class);
303
392
304
393
$ this ->assertSame ('01/10/2018 ' , $ denormalizedDate ->format ($ format ));
@@ -309,7 +398,7 @@ public function testDenormalizeDateTimeStringWithDefaultContextAllowsErrorFormat
309
398
$ format = 'd/m/Y ' ; // the default format
310
399
$ string = '2020-01-01 ' ; // the value which is in the wrong format, but is accepted because of `new \DateTimeImmutable` in DateTimeNormalizer::denormalize
311
400
312
- $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::FORMAT_KEY => $ format ]);
401
+ $ normalizer = new DateTimeNormalizer ([DateTimeNormalizer::FORMAT_KEY => $ format, DateTimeNormalizer:: TIMESTAMP_CAST_KEY => true ]);
313
402
$ denormalizedDate = $ normalizer ->denormalize ($ string , \DateTimeInterface::class);
314
403
315
404
$ this ->assertSame ('2020-01-01 ' , $ denormalizedDate ->format ('Y-m-d ' ));
@@ -320,4 +409,18 @@ public function testDenormalizeFormatMismatchThrowsException()
320
409
$ this ->expectException (UnexpectedValueException::class);
321
410
$ this ->normalizer ->denormalize ('2016-01-01T00:00:00+00:00 ' , \DateTimeInterface::class, null , [DateTimeNormalizer::FORMAT_KEY => 'Y-m-d| ' ]);
322
411
}
412
+
413
+ /**
414
+ * @testWith ["U"]
415
+ * ["U.u"]
416
+ * [null]
417
+ *
418
+ * @group legacy
419
+ */
420
+ public function testDeprecationWithoutTimestampCast (?string $ format )
421
+ {
422
+ $ this ->expectDeprecation ('Since symfony/serializer 7.1: Not setting the "datetime_timestamp_cast" in defaultContext for "Symfony\Component\Serializer\Normalizer\DateTimeNormalizer" is deprecated. It will default to "true" in 8.0. ' );
423
+
424
+ (new DateTimeNormalizer ())->normalize (new \DateTimeImmutable (), null , $ format !== null ? [DateTimeNormalizer::FORMAT_KEY => $ format ] : []);
425
+ }
323
426
}
0 commit comments