8000 [Form] Fixed reverse transformation of values in DateTimeToStringTransformer by webmozart · Pull Request #6333 · symfony/symfony · GitHub
[go: up one dir, main page]

Skip to content

[Form] Fixed reverse transformation of values in DateTimeToStringTransformer #6333

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 13, 2012
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
8000
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -32,12 +32,12 @@ class DateTimeToLocalizedStringTransformer extends BaseDateTimeTransformer
*
* @see BaseDateTimeTransformer::formats for available format options
*
* @param string $inputTimezone The name of the input timezone
* @param string $outputTimezone The name of the output timezone
* @param integer $dateFormat The date format
* @param integer $timeFormat The time format
* @param \IntlDateFormatter $calendar An \IntlDateFormatter instance
* @param string $pattern A pattern to pass to \IntlDateFormatter
* @param string $inputTimezone The name of the input timezone
* @param string $outputTimezone The name of the output timezone
* @param integer $dateFormat The date format
* @param integer $timeFormat The time format
* @param integer $calendar One of the \IntlDateFormatter calendar constants
* @param string $pattern A pattern to pass to \IntlDateFormatter
*
* @throws UnexpectedTypeException If a format is not supported
* @throws UnexpectedTypeException if a timezone is not a string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,22 @@
*/
class DateTimeToStringTransformer extends BaseDateTimeTransformer
{
private $format;
/**
* Format used for generating strings
* @var string
*/
private $generateFormat;

/**
* Format used for parsing strings
*
* Different than the {@link $generateFormat} because formats for parsing
* support additional characters in PHP that are not supported for
* generating strings.
*
* @var string
*/
private $parseFormat;

/**
* Transforms a \DateTime instance to a string
Expand All @@ -39,14 +54,26 @@ public function __construct($inputTimezone = null, $outputTimezone = null, $form
{
parent::__construct($inputTimezone, $outputTimezone);

$this->format = $format;
$this->generateFormat = $this->parseFormat = $format;

// See http://php.net/manual/en/datetime.createfromformat.php
// The character "|" in the format makes sure that the parts of a date
// that are *not* specified in the format are reset to the corresponding
// values from 1970-01-01 00:00:00 instead of the current time.
// Without "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 12:32:47",
// where the time corresponds to the current server time.
// With "|" and "Y-m-d", "2010-02-03" becomes "2010-02-03 00:00:00",
// which is at least deterministic and thus used here.
if (false === strpos($this->parseFormat, '|')) {
$this->parseFormat .= '|';
}
}

/**
* Transforms a DateTime object into a date string with the configured format
* and timezone
*
* @param DateTime $value A DateTime object
* @param \DateTime $value A DateTime object
*
* @return string A value as produced by PHP's date() function
*
Expand All @@ -70,15 +97,15 @@ public function transform($value)
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}

return $value->format($this->format);
return $value->format($this->generateFormat);
}

/**
* Transforms a date string in the configured timezone into a DateTime object.
*
* @param string $value A value as produced by PHP's date() function
*
* @return \DateTime An instance of \DateTime
* @return \DateTime An instance of \DateTime
*
* @throws UnexpectedTypeException if the given value is not a string
* @throws TransformationFailedException if the date could not be parsed
Expand All @@ -95,20 +122,25 @@ public function reverseTransform($value)
}

try {
$dateTime = new \DateTime($value, new \DateTimeZone($this->outputTimezone));
$outputTz = new \DateTimeZone($this->outputTimezone);
$dateTime = \DateTime::createFromFormat($this->parseFormat, $value, $outputTz);

$lastErrors = \DateTime::getLastErrors();
if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) {
throw new \UnexpectedValueException(implode(', ', array_merge(array_values($lastErrors['warnings']), array_values($lastErrors['errors']))));
}

// Force value to be in same format as given to transform
if ($value !== $dateTime->format($this->format)) {
$dateTime = new \DateTime($dateTime->format($this->format), new \DateTimeZone($this->outputTimezone));
if (0 < $lastErrors['warning_count'] || 0 < $lastErrors['error_count']) {
throw new TransformationFailedException(
implode(', ', array_merge(
array_values($lastErrors['warnings']),
array_values($lastErrors['errors'])
))
);
}

if ($this->inputTimezone !== $this->outputTimezone) {
$dateTime->setTimeZone(new \DateTimeZone($this->inputTimezone));
}
} catch (TransformationFailedException $e) {
throw $e;
} catch (\Exception $e) {
throw new TransformationFailedException($e->getMessage(), $e->getCode(), $e);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ protected function tearDown()
$this->dateTimeWithoutSeconds = null;
}

public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = FALSE, $ignoreCase = FALSE)
public static function assertEquals($expected, $actual, $message = '', $delta = 0, $maxDepth = 10, $canonicalize = false, $ignoreCase = false)
{
if ($expected instanceof \DateTime && $actual instanceof \DateTime) {
$expected = $expected->format('c');
Expand All @@ -44,54 +44,59 @@ public static function assertEquals($expected, $actual, $message = '', $delta =
parent::assertEquals($expected, $actual, $message, $delta, $maxDepth, $canonicalize, $ignoreCase);
}

public function testTransformShortDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT);
$this->assertEquals('03.02.10 04:05', $transformer->transform($this->dateTime));
}

public function testTransformMediumDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::MEDIUM);

$this->assertEquals('03.02.2010 04:05', $transformer->transform($this->dateTime));
}

public function testTransformLongDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::LONG);

$this->assertEquals('03. Februar 2010 04:05', $transformer->transform($this->dateTime));
}

public function testTransformFullDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL);

$this->assertEquals('Mittwoch, 03. Februar 2010 04:05', $transformer->transform($this->dateTime));
public function dataProvider()
{
return array(
array(\IntlDateFormatter::SHORT, null, null, '03.02.10 04:05', '2010-02-03 04:05:00 UTC'),
array(\IntlDateFormatter::MEDIUM, null, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'),
array(\IntlDateFormatter::LONG, null, null, '03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'),
array(\IntlDateFormatter::FULL, null, null, 'Mittwoch, 03. Februar 2010 04:05', '2010-02-03 04:05:00 UTC'),
array(\IntlDateFormatter::SHORT, \IntlDateFormatter::NONE, null, '03.02.10', '2010-02-03 00:00:00 UTC'),
array(\IntlDateFormatter::MEDIUM, \IntlDateFormatter::NONE, null, '03.02.2010', '2010-02-03 00:00:00 UTC'),
array(\IntlDateFormatter::LONG, \IntlDateFormatter::NONE, null, '03. Februar 2010', '2010-02-03 00:00:00 UTC'),
array(\IntlDateFormatter::FULL, \IntlDateFormatter::NONE, null, 'Mittwoch, 03. Februar 2010', '2010-02-03 00:00:00 UTC'),
array(null, \IntlDateFormatter::SHORT, null, '03.02.2010 04:05', '2010-02-03 04:05:00 UTC'),
array(null, \IntlDateFormatter::MEDIUM, null, '03.02.2010 04:05:06', '2010-02-03 04:05:06 UTC'),
array(null, \IntlDateFormatter::LONG, null,
'03.02.2010 04:05:06 GMT' . ($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''),
'2010-02-03 04:05:06 UTC'),
// see below for extra test case for time format FULL
array(\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT, null, '04:05', '1970-01-01 04:05:00 UTC'),
array(\IntlDateFormatter::NONE, \IntlDateFormatter::MEDIUM, null, '04:05:06', '1970-01-01 04:05:06 UTC'),
array(\IntlDateFormatter::NONE, \IntlDateFormatter::LONG, null,
'04:05:06 GMT' . ($this->isLowerThanIcuVersion('4.8') ? '+00:00' : ''),
'1970-01-01 04:05:06 UTC'),
array(null, null, 'yyyy-MM-dd HH:mm:00', '2010-02-03 04:05:00', '2010-02-03 04:05:00 UTC'),
array(null, null, 'yyyy-MM-dd HH:mm', '2010-02-03 04:05', '2010-02-03 04:05:00 UTC'),
array(null, null, 'yyyy-MM-dd HH', '2010-02-03 04', '2010-02-03 04:00:00 UTC'),
array(null, null, 'yyyy-MM-dd', '2010-02-03', '2010-02-03 00:00:00 UTC'),
array(null, null, 'yyyy-MM', '2010-02', '2010-02-01 00:00:00 UTC'),
array(null, null, 'yyyy', '2010', '2010-01-01 00:00:00 UTC'),
array(null, null, 'dd-MM-yyyy', '03-02-2010', '2010-02-03 00:00:00 UTC'),
array(null, null, 'HH:mm:ss', '04:05:06', '1970-01-01 04:05:06 UTC'),
array(null, null, 'HH:mm:00', '04:05:00', '1970-01-01 04:05:00 UTC'),
array(null, null, 'HH:mm', '04:05', '1970-01-01 04:05:00 UTC'),
array(null, null, 'HH', '04', '1970-01-01 04:00:00 UTC'),
);
}

public function testTransformShortTime()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::SHORT);

$this->assertEquals('03.02.2010 04:05', $transformer->transform($this->dateTime));
}

public function testTransformMediumTime()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::MEDIUM);

$this->assertEquals('03.02.2010 04:05:06', $transformer->transform($this->dateTime));
}

public function testTransformLongTime()
/**
* @dataProvider dataProvider
*/
public function testTransform($dateFormat, $timeFormat, $pattern, $output, $input)
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::LONG);
$transformer = new DateTimeToLocalizedStringTransformer(
'UTC',
'UTC',
$dateFormat,
$timeFormat,
\IntlDateFormatter::GREGORIAN,
$pattern
);

$expected = $this->isLowerThanIcuVersion('4.8') ? '03.02.2010 04:05:06 GMT+00:00' : '03.02.2010 04:05:06 GMT';
$input = new \DateTime($input);

$this->assertEquals($expected, $transformer->transform($this->dateTime));
$this->assertEquals($output, $transformer->transform($input));
}

public function testTransformFullTime()
Expand Down Expand Up @@ -143,7 +148,7 @@ public function testTransform_differentPatterns()
}

/**
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testTransformRequiresValidDateTime()
{
Expand All @@ -162,53 +167,23 @@ public function testTransformWrapsIntlErrors()
//$transformer->transform(1.5);
}

public function testReverseTransformShortDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::SHORT);

$this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('03.02.10 04:05'));
}

public function testReverseTransformMediumDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::MEDIUM);

$this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('03.02.2010 04:05'));
}

public function testReverseTransformLongDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::LONG);

$this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('03. Februar 2010 04:05'));
}

public function testReverseTransformFullDate()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', \IntlDateFormatter::FULL);

$this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('Mittwoch, 03. Februar 2010 04:05'));
}

public function testReverseTransformShortTime()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::SHORT);

$this->assertDateTimeEquals($this->dateTimeWithoutSeconds, $transformer->reverseTransform('03.02.2010 04:05'));
}

public function testReverseTransformMediumTime()
/**
* @dataProvider dataProvider
*/
public function testReverseTransform($dateFormat, $timeFormat, $pattern, $input, $output)
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::MEDIUM);

$this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010 04:05:06'));
}
$transformer = new DateTimeToLocalizedStringTransformer(
'UTC',
'UTC',
$dateFormat,
$timeFormat,
\IntlDateFormatter::GREGORIAN,
$pattern
);

public function testReverseTransformLongTime()
{
$transformer = new DateTimeToLocalizedStringTransformer('UTC', 'UTC', null, \IntlDateFormatter::LONG);
$output = new \DateTime($output);

$this->assertDateTimeEquals($this->dateTime, $transformer->reverseTransform('03.02.2010 04:05:06 GMT+00:00'));
$this->assertEquals($output, $transformer->reverseTransform($input));
}

public function testReverseTransformFullTime()
Expand Down Expand Up @@ -256,7 +231,7 @@ public function testReverseTransform_empty()
}

/**
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testReverseTransformRequiresString()
{
Expand All @@ -265,7 +240,7 @@ public function testReverseTransformRequiresString()
}

/**
* @expectedException Symfony\Component\Form\Exception\TransformationFailedException
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformWrapsIntlErrors()
{
Expand All @@ -274,23 +249,23 @@ public function testReverseTransformWrapsIntlErrors()
}

/**
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testValidateDateFormatOption()
{
new DateTimeToLocalizedStringTransformer(null, null, 'foobar');
}

/**
* @expectedException Symfony\Component\Form\Exception\UnexpectedTypeException
* @expectedException \Symfony\Component\Form\Exception\UnexpectedTypeException
*/
public function testValidateTimeFormatOption()
{
new DateTimeToLocalizedStringTransformer(null, null, null, 'foobar');
}

/**
* @expectedException Symfony\Component\Form\Exception\TransformationFailedException
* @expectedException \Symfony\Component\Form\Exception\TransformationFailedException
*/
public function testReverseTransformWithNonExistingDate()
{
Expand Down
Loading
0