Skip to content

Commit db6fbf9

Browse files
bug symfony#46216 [Form] fix populating single widget time view data with different timezones (xabbuh)
This PR was merged into the 4.4 branch. Discussion ---------- [Form] fix populating single widget time view data with different timezones | Q | A | ------------- | --- | Branch? | 4.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix symfony#46137 | License | MIT | Doc PR | Commits ------- 430f7c4 [Form] fix populating single widget time view data with different timezones
2 parents 3a54735 + 430f7c4 commit db6fbf9

File tree

3 files changed

+78
-4
lines changed

3 files changed

+78
-4
lines changed

src/Symfony/Component/Form/Extension/Core/DataTransformer/DateTimeToStringTransformer.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,12 +47,14 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
4747
* @param string|null $inputTimezone The name of the input timezone
4848
* @param string|null $outputTimezone The name of the output timezone
4949
* @param string $format The date format
50+
* @param string|null $parseFormat The parse format when different from $format
5051
*/
51-
public function __construct(string $inputTimezone = null, string $outputTimezone = null, string $format = 'Y-m-d H:i:s')
52+
public function __construct(string $inputTimezone = null, string $outputTimezone = null, string $format = 'Y-m-d H:i:s', string $parseFormat = null)
5253
{
5354
parent::__construct($inputTimezone, $outputTimezone);
5455

55-
$this->generateFormat = $this->parseFormat = $format;
56+
$this->generateFormat = $format;
57+
$this->parseFormat = $parseFormat ?? $format;
5658

5759
// See https://php.net/datetime.createfromformat
5860
// The character "|" in the format makes sure that the parts of a date

src/Symfony/Component/Form/Extension/Core/Type/TimeType.php

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -73,8 +73,10 @@ public function buildForm(FormBuilderInterface $builder, array $options)
7373
}
7474
});
7575

76+
$parseFormat = null;
77+
7678
if (null !== $options['reference_date']) {
77-
$format = 'Y-m-d '.$format;
79+
$parseFormat = 'Y-m-d '.$format;
7880

7981
$builder->addEventListener(FormEvents::PRE_SUBMIT, function (FormEvent $event) use ($options) {
8082
$data = $event->getData();
@@ -85,7 +87,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
8587
});
8688
}
8789

88-
$builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format));
90+
$builder->addViewTransformer(new DateTimeToStringTransformer($options['model_timezone'], $options['view_timezone'], $format, $parseFormat));
8991
} else {
9092
$hourOptions = $minuteOptions = $secondOptions = [
9193
'error_bubbling' => true,

src/Symfony/Component/Form/Tests/Extension/Core/Type/TimeTypeTest.php

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,76 @@ public function testSubmitWithSecondsAndBrowserOmissionSeconds()
279279
$this->assertEquals('03:04:00', $form->getViewData());
280280
}
281281

282+
public function testPreSetDataDifferentTimezones()
283+
{
284+
$form = $this->factory->create(static::TESTED_TYPE, null, [
285+
'model_timezone' => 'UTC',
286+
'view_timezone' => 'Europe/Berlin',
287+
'input' => 'datetime',
288+
'with_seconds' => true,
289+
'reference_date' => new \DateTimeImmutable('2019-01-01', new \DateTimeZone('UTC')),
290+
]);
291+
$form->setData(new \DateTime('2022-01-01 15:09:10', new \DateTimeZone('UTC')));
292+
293+
$this->assertSame('15:09:10', $form->getData()->format('H:i:s'));
294+
$this->assertSame([
295+
'hour' => '16',
296+
'minute' => '9',
297+
'second' => '10',
298+
], $form->getViewData());
299+
}
300+
301+
public function testPreSetDataDifferentTimezonesDuringDaylightSavingTime()
302+
{
303+
$form = $this->factory->create(static::TESTED_TYPE, null, [
304+
'model_timezone' => 'UTC',
305+
'view_timezone' => 'Europe/Berlin',
306+
'input' => 'datetime',
307+
'with_seconds' => true,
308+
'reference_date' => new \DateTimeImmutable('2019-07-12', new \DateTimeZone('UTC')),
309+
]);
310+
$form->setData(new \DateTime('2022-04-29 15:09:10', new \DateTimeZone('UTC')));
311+
312+
$this->assertSame('15:09:10', $form->getData()->format('H:i:s'));
313+
$this->assertSame([
314+
'hour' => '17',
315+
'minute' => '9',
316+
'second' => '10',
317+
], $form->getViewData());
318+
}
319+
320+
public function testPreSetDataDifferentTimezonesUsingSingleTextWidget()
321+
{
322+
$form = $this->factory->create(static::TESTED_TYPE, null, [
323+
'model_timezone' => 'UTC',
324+
'view_timezone' => 'Europe/Berlin',
325+
'input' => 'datetime',
326+
'with_seconds' => true,
327+
'reference_date' => new \DateTimeImmutable('2019-01-01', new \DateTimeZone('UTC')),
328+
'widget' => 'single_text',
329+
]);
330+
$form->setData(new \DateTime('2022-01-01 15:09:10', new \DateTimeZone('UTC')));
331+
332+
$this->assertSame('15:09:10', $form->getData()->format('H:i:s'));
333+
$this->assertSame('16:09:10', $form->getViewData());
334+
}
335+
336+
public function testPreSetDataDifferentTimezonesDuringDaylightSavingTimeUsingSingleTextWidget()
337+
{
338+
$form = $this->factory->create(static::TESTED_TYPE, null, [
339+
'model_timezone' => 'UTC',
340+
'view_timezone' => 'Europe/Berlin',
341+
'input' => 'datetime',
342+
'with_seconds' => true,
343+
'reference_date' => new \DateTimeImmutable('2019-07-12', new \DateTimeZone('UTC')),
344+
'widget' => 'single_text',
345+
]);
346+
$form->setData(new \DateTime('2022-04-29 15:09:10', new \DateTimeZone('UTC')));
347+
348+
$this->assertSame('15:09:10', $form->getData()->format('H:i:s'));
349+
$this->assertSame('17:09:10', $form->getViewData());
350+
}
351+
282352
public function testSubmitDifferentTimezones()
283353
{
284354
$form = $this->factory->create(static::TESTED_TYPE, null, [

0 commit comments

Comments
 (0)