From 2f85fe4c2f5df2bbff13d52f239fcbbe0eedd775 Mon Sep 17 00:00:00 2001 From: Luis Galeas Date: Wed, 14 Dec 2016 15:35:27 +0000 Subject: [PATCH] DateIntervalType (negative support) resolves doctrine/dbal#2578 --- lib/Doctrine/DBAL/Types/DateIntervalType.php | 22 ++++++++++--- .../Tests/DBAL/Types/DateIntervalTest.php | 33 ++++++++++++++++--- 2 files changed, 47 insertions(+), 8 deletions(-) diff --git a/lib/Doctrine/DBAL/Types/DateIntervalType.php b/lib/Doctrine/DBAL/Types/DateIntervalType.php index 27d1369bd93..9891cf808fa 100644 --- a/lib/Doctrine/DBAL/Types/DateIntervalType.php +++ b/lib/Doctrine/DBAL/Types/DateIntervalType.php @@ -22,7 +22,7 @@ public function getName() */ public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform) { - $fieldDeclaration['length'] = 20; + $fieldDeclaration['length'] = 21; $fieldDeclaration['fixed'] = true; return $platform->getVarcharTypeDeclarationSQL($fieldDeclaration); @@ -38,7 +38,9 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform) } if ($value instanceof \DateInterval) { - return 'P' + $sign = (0 === $value->invert) ? '+' : '-'; + + return $sign . 'P' . str_pad($value->y, 4, '0', STR_PAD_LEFT) . '-' . $value->format('%M-%DT%H:%I:%S'); } @@ -56,9 +58,21 @@ public function convertToPHPValue($value, AbstractPlatform $platform) } try { - return new \DateInterval($value); + $firstCharacter = substr($value, 0, 1); + + if ($firstCharacter !== '+' && $firstCharacter !== '-') { + return new \DateInterval($value); + } + + $interval = new \DateInterval(substr($value, 1)); + + if ($firstCharacter === '-') { + $interval->invert = 1; + } + + return $interval; } catch (\Exception $exception) { - throw ConversionException::conversionFailedFormat($value, $this->getName(), 'PY-m-dTH:i:s', $exception); + throw ConversionException::conversionFailedFormat($value, $this->getName(), 'RPY-m-dTH:i:s', $exception); } } diff --git a/tests/Doctrine/Tests/DBAL/Types/DateIntervalTest.php b/tests/Doctrine/Tests/DBAL/Types/DateIntervalTest.php index 8d212001a71..3415b1f64b2 100644 --- a/tests/Doctrine/Tests/DBAL/Types/DateIntervalTest.php +++ b/tests/Doctrine/Tests/DBAL/Types/DateIntervalTest.php @@ -32,7 +32,7 @@ public function testDateIntervalConvertsToDatabaseValue() { $interval = new \DateInterval('P2Y1DT1H2M3S'); - $expected = 'P0002-00-01T01:02:03'; + $expected = '+P0002-00-01T01:02:03'; $actual = $this->type->convertToDatabaseValue($interval, $this->platform); $this->assertEquals($expected, $actual); @@ -40,9 +40,34 @@ public function testDateIntervalConvertsToDatabaseValue() public function testDateIntervalConvertsToPHPValue() { - $date = $this->type->convertToPHPValue('P0002-00-01T01:02:03', $this->platform); - $this->assertInstanceOf('DateInterval', $date); - $this->assertEquals('P2Y0M1DT1H2M3S', $date->format('P%yY%mM%dDT%hH%iM%sS')); + $interval = $this->type->convertToPHPValue('+P0002-00-01T01:02:03', $this->platform); + $this->assertInstanceOf('DateInterval', $interval); + $this->assertEquals('+P2Y0M1DT1H2M3S', $interval->format('%RP%yY%mM%dDT%hH%iM%sS')); + } + + public function testOldDateIntervalFormatConvertsToPHPValue() + { + $interval = $this->type->convertToPHPValue('P0002-00-01T01:02:03', $this->platform); + $this->assertInstanceOf('DateInterval', $interval); + $this->assertEquals('+P2Y0M1DT1H2M3S', $interval->format('%RP%yY%mM%dDT%hH%iM%sS')); + } + + public function testNegativeDateIntervalConvertsToDatabaseValue() + { + $interval = new \DateInterval('P2Y1DT1H2M3S'); + $interval->invert = 1; + + $expected = '-P0002-00-01T01:02:03'; + $actual = $this->type->convertToDatabaseValue($interval, $this->platform); + + $this->assertEquals($expected, $actual); + } + + public function testNegativeDateIntervalConvertsToPHPValue() + { + $interval = $this->type->convertToPHPValue('-P0002-00-01T01:02:03', $this->platform); + $this->assertInstanceOf('DateInterval', $interval); + $this->assertEquals('-P2Y0M1DT1H2M3S', $interval->format('%RP%yY%mM%dDT%hH%iM%sS')); } public function testInvalidDateIntervalFormatConversion()