bug #14895 [Form] Support DateTimeImmutable in transform() (c960657)
This PR was merged into the 2.3 branch.
Discussion
----------
[Form] Support DateTimeImmutable in transform()
| Q | A
| ------------- | ---
| Bug fix? | yes
| New feature? | yes
| BC breaks? | no
| Deprecations? | no
| Tests pass? | yes
| Fixed tickets |
| License | MIT
| Doc PR |
When passing a DateTimeImmutable instance to DateTimeToLocalizedStringTransformer::transform($dateTime), it throws an exception, `TransformationFailedException('Expected a \DateTime.')`.
The method just converts a date-time object into a string, so there is no reason that it should not support all DateTimeInterface implementations.
DateTimeInterface was added in PHP 5.5, so in order to support earlier versions, we need to do instanceof checks for both DateTime and DateTimeInterface. When Symfony requires PHP 5.5 or larger, we can remove the DateTime check and only check for DateTimeInterface.
This was originally submitted as a PR against the 2.7 branch in #14676.
Commits
-------
17346c5
[Form] Support DateTimeImmutable in transform()
This commit is contained in:
commit
a48d36ae31
|
@ -51,7 +51,7 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
|
|||
/**
|
||||
* Transforms a normalized date into a localized date.
|
||||
*
|
||||
* @param \DateTime $dateTime Normalized date.
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return array Localized date.
|
||||
*
|
||||
|
@ -72,14 +72,17 @@ class DateTimeToArrayTransformer extends BaseDateTimeTransformer
|
|||
), array_flip($this->fields));
|
||||
}
|
||||
|
||||
if (!$dateTime instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
$dateTime = clone $dateTime;
|
||||
if ($this->inputTimezone !== $this->outputTimezone) {
|
||||
if (!$dateTime instanceof \DateTimeImmutable) {
|
||||
$dateTime = clone $dateTime;
|
||||
}
|
||||
|
||||
try {
|
||||
$dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
|
|||
/**
|
||||
* Transforms a normalized date into a localized date string/array.
|
||||
*
|
||||
* @param \DateTime $dateTime Normalized date.
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return string|array Localized date string/array.
|
||||
*
|
||||
|
@ -84,17 +84,11 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
|
|||
return '';
|
||||
}
|
||||
|
||||
if (!$dateTime instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
// convert time to UTC before passing it to the formatter
|
||||
$dateTime = clone $dateTime;
|
||||
if ('UTC' !== $this->inputTimezone) {
|
||||
$dateTime->setTimezone(new \DateTimeZone('UTC'));
|
||||
}
|
||||
|
||||
$value = $this->getIntlDateFormatter()->format((int) $dateTime->format('U'));
|
||||
$value = $this->getIntlDateFormatter()->format($dateTime->getTimestamp());
|
||||
|
||||
if (intl_get_error_code() != 0) {
|
||||
throw new TransformationFailedException(intl_get_error_message());
|
||||
|
|
|
@ -27,13 +27,13 @@ class DateTimeToRfc3339Transformer extends BaseDateTimeTransformer
|
|||
return '';
|
||||
}
|
||||
|
||||
if (!$dateTime instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$dateTime instanceof \DateTime && !$dateTime instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
if ($this->inputTimezone !== $this->outputTimezone) {
|
||||
$dateTime = clone $dateTime;
|
||||
$dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
}
|
||||
|
||||
return preg_replace('/\+00:00$/', 'Z', $dateTime->format('c'));
|
||||
|
|
|
@ -90,7 +90,7 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
|
|||
* Transforms a DateTime object into a date string with the configured format
|
||||
* and timezone.
|
||||
*
|
||||
* @param \DateTime $value A DateTime object
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return string A value as produced by PHP's date() function
|
||||
*
|
||||
|
@ -104,13 +104,16 @@ class DateTimeToStringTransformer extends BaseDateTimeTransformer
|
|||
return '';
|
||||
}
|
||||
|
||||
if (!$value instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
if (!$value instanceof \DateTimeImmutable) {
|
||||
$value = clone $value;
|
||||
}
|
||||
|
||||
$value = clone $value;
|
||||
try {
|
||||
$value->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
$value = $value->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
|
|
@ -24,7 +24,7 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
|
|||
/**
|
||||
* Transforms a DateTime object into a timestamp in the configured timezone.
|
||||
*
|
||||
* @param \DateTime $value A \DateTime object
|
||||
* @param \DateTime|\DateTimeInterface $dateTime A DateTime object
|
||||
*
|
||||
* @return int A timestamp
|
||||
*
|
||||
|
@ -38,18 +38,11 @@ class DateTimeToTimestampTransformer extends BaseDateTimeTransformer
|
|||
return;
|
||||
}
|
||||
|
||||
if (!$value instanceof \DateTime) {
|
||||
throw new TransformationFailedException('Expected a \DateTime.');
|
||||
if (!$value instanceof \DateTime && !$value instanceof \DateTimeInterface) {
|
||||
throw new TransformationFailedException('Expected a \DateTime or \DateTimeInterface.');
|
||||
}
|
||||
|
||||
$value = clone $value;
|
||||
try {
|
||||
$value->setTimezone(new \DateTimeZone($this->outputTimezone));
|
||||
} catch (\Exception $e) {
|
||||
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
|
||||
}
|
||||
|
||||
return (int) $value->format('U');
|
||||
return $value->getTimestamp();
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -116,6 +116,30 @@ class DateTimeToArrayTransformerTest extends DateTimeTestCase
|
|||
$this->assertSame($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutable()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToArrayTransformer('America/New_York', 'Asia/Hong_Kong');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
|
||||
$dateTime = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
$output = array(
|
||||
'year' => (string) (int) $dateTime->format('Y'),
|
||||
'month' => (string) (int) $dateTime->format('m'),
|
||||
'day' => (string) (int) $dateTime->format('d'),
|
||||
'hour' => (string) (int) $dateTime->format('H'),
|
||||
'minute' => (string) (int) $dateTime->format('i'),
|
||||
'second' => (string) (int) $dateTime->format('s'),
|
||||
);
|
||||
|
||||
$this->assertSame($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
|
|
|
@ -141,6 +141,22 @@ class DateTimeToLocalizedStringTransformerTest extends DateTimeTestCase
|
|||
$this->assertEquals('02*2010*03 04|05|06', $transformer->transform($this->dateTime));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutableTimezones()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToLocalizedStringTransformer('America/New_York', 'Asia/Hong_Kong');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
|
||||
$dateTime = clone $input;
|
||||
$dateTime = $dateTime->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
|
||||
$this->assertEquals($dateTime->format('d.m.Y H:i'), $transformer->transform($input));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
|
|
|
@ -79,6 +79,20 @@ class DateTimeToRfc3339TransformerTest extends DateTimeTestCase
|
|||
$this->assertSame($to, $transformer->transform(null !== $from ? new \DateTime($from) : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider transformProvider
|
||||
*/
|
||||
public function testTransformDateTimeImmutable($fromTz, $toTz, $from, $to)
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToRfc3339Transformer($fromTz, $toTz);
|
||||
|
||||
$this->assertSame($to, $transformer->transform(null !== $from ? new \DateTimeImmutable($from) : null));
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
|
||||
*/
|
||||
|
|
|
@ -97,6 +97,21 @@ class DateTimeToStringTransformerTest extends DateTimeTestCase
|
|||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutable()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToStringTransformer('Asia/Hong_Kong', 'America/New_York', 'Y-m-d H:i:s');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 12:05:06 America/New_York');
|
||||
$output = $input->format('Y-m-d H:i:s');
|
||||
$input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
|
||||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformExpectsDateTime()
|
||||
{
|
||||
$transformer = new DateTimeToStringTransformer();
|
||||
|
|
|
@ -56,6 +56,21 @@ class DateTimeToTimestampTransformerTest extends DateTimeTestCase
|
|||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformDateTimeImmutable()
|
||||
{
|
||||
if (PHP_VERSION_ID < 50500) {
|
||||
$this->markTestSkipped('DateTimeImmutable was introduced in PHP 5.5.0');
|
||||
}
|
||||
|
||||
$transformer = new DateTimeToTimestampTransformer('Asia/Hong_Kong', 'America/New_York');
|
||||
|
||||
$input = new \DateTimeImmutable('2010-02-03 04:05:06 America/New_York');
|
||||
$output = $input->format('U');
|
||||
$input = $input->setTimezone(new \DateTimeZone('Asia/Hong_Kong'));
|
||||
|
||||
$this->assertEquals($output, $transformer->transform($input));
|
||||
}
|
||||
|
||||
public function testTransformExpectsDateTime()
|
||||
{
|
||||
$transformer = new DateTimeToTimestampTransformer();
|
||||
|
|
Reference in New Issue