Skip to content

Commit 792c5b5

Browse files
authored
Merge pull request #2579 from galeaspablo/fix/date_interval_type
DateIntervalType (negative support) resolves #2578
2 parents 61c5e4e + 7c97593 commit 792c5b5

File tree

2 files changed

+51
-21
lines changed

2 files changed

+51
-21
lines changed

lib/Doctrine/DBAL/Types/DateIntervalType.php

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,15 @@
33
namespace Doctrine\DBAL\Types;
44

55
use Doctrine\DBAL\Platforms\AbstractPlatform;
6+
use function substr;
67

78
/**
89
* Type that maps interval string to a PHP DateInterval Object.
910
*/
1011
class DateIntervalType extends Type
1112
{
13+
public const FORMAT = '%RP%YY%MM%DDT%HH%IM%SS';
14+
1215
/**
1316
* {@inheritdoc}
1417
*/
@@ -38,7 +41,7 @@ public function convertToDatabaseValue($value, AbstractPlatform $platform)
3841
}
3942

4043
if ($value instanceof \DateInterval) {
41-
return $value->format('P%YY%MM%DDT%HH%IM%SS');
44+
return $value->format(self::FORMAT);
4245
}
4346

4447
throw ConversionException::conversionFailedInvalidType($value, $this->getName(), ['null', 'DateInterval']);
@@ -54,9 +57,15 @@ public function convertToPHPValue($value, AbstractPlatform $platform)
5457
}
5558

5659
try {
57-
return new \DateInterval($value);
60+
$interval = new \DateInterval(substr($value, 1));
61+
62+
if (substr($value, 0, 1) === '-') {
63+
$interval->invert = 1;
64+
}
65+
66+
return $interval;
5867
} catch (\Exception $exception) {
59-
throw ConversionException::conversionFailedFormat($value, $this->getName(), 'P%YY%MM%DDT%HH%IM%SS', $exception);
68+
throw ConversionException::conversionFailedFormat($value, $this->getName(), self::FORMAT, $exception);
6069
}
6170
}
6271

tests/Doctrine/Tests/DBAL/Types/DateIntervalTest.php

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,13 @@
22

33
namespace Doctrine\Tests\DBAL\Types;
44

5+
use Doctrine\DBAL\Types\ConversionException;
6+
use Doctrine\DBAL\Types\DateIntervalType;
57
use Doctrine\DBAL\Types\Type;
68
use Doctrine\Tests\DBAL\Mocks\MockPlatform;
9+
use Doctrine\Tests\DbalTestCase;
710

8-
class DateIntervalTest extends \Doctrine\Tests\DbalTestCase
11+
final class DateIntervalTest extends DbalTestCase
912
{
1013
/**
1114
* @var MockPlatform
@@ -20,66 +23,84 @@ class DateIntervalTest extends \Doctrine\Tests\DbalTestCase
2023
/**
2124
* {@inheritDoc}
2225
*/
23-
protected function setUp()
26+
protected function setUp() : void
2427
{
2528
$this->platform = new MockPlatform();
2629
$this->type = Type::getType('dateinterval');
2730

28-
self::assertInstanceOf('Doctrine\DBAL\Types\DateIntervalType', $this->type);
31+
self::assertInstanceOf(DateIntervalType::class, $this->type);
2932
}
3033

31-
public function testDateIntervalConvertsToDatabaseValue()
34+
public function testDateIntervalConvertsToDatabaseValue() : void
3235
{
3336
$interval = new \DateInterval('P2Y1DT1H2M3S');
3437

35-
$expected = 'P02Y00M01DT01H02M03S';
38+
$expected = '+P02Y00M01DT01H02M03S';
3639
$actual = $this->type->convertToDatabaseValue($interval, $this->platform);
3740

3841
self::assertEquals($expected, $actual);
3942
}
4043

41-
public function testDateIntervalConvertsToPHPValue()
44+
public function testDateIntervalConvertsToPHPValue() : void
4245
{
43-
$date = $this->type->convertToPHPValue('P02Y00M01DT01H02M03S', $this->platform);
44-
self::assertInstanceOf('DateInterval', $date);
45-
self::assertEquals('P02Y00M01DT01H02M03S', $date->format('P%YY%MM%DDT%HH%IM%SS'));
46+
$interval = $this->type->convertToPHPValue('+P02Y00M01DT01H02M03S', $this->platform);
47+
48+
self::assertInstanceOf(\DateInterval::class, $interval);
49+
self::assertEquals('+P02Y00M01DT01H02M03S', $interval->format(DateIntervalType::FORMAT));
50+
}
51+
52+
public function testNegativeDateIntervalConvertsToDatabaseValue() : void
53+
{
54+
$interval = new \DateInterval('P2Y1DT1H2M3S');
55+
$interval->invert = 1;
56+
57+
$actual = $this->type->convertToDatabaseValue($interval, $this->platform);
58+
59+
self::assertEquals('-P02Y00M01DT01H02M03S', $actual);
60+
}
61+
62+
public function testNegativeDateIntervalConvertsToPHPValue() : void
63+
{
64+
$interval = $this->type->convertToPHPValue('-P02Y00M01DT01H02M03S', $this->platform);
65+
66+
self::assertInstanceOf(\DateInterval::class, $interval);
67+
self::assertEquals('-P02Y00M01DT01H02M03S', $interval->format(DateIntervalType::FORMAT));
4668
}
4769

48-
public function testInvalidDateIntervalFormatConversion()
70+
public function testInvalidDateIntervalFormatConversion() : void
4971
{
50-
$this->expectException('Doctrine\DBAL\Types\ConversionException');
72+
$this->expectException(ConversionException::class);
73+
5174
$this->type->convertToPHPValue('abcdefg', $this->platform);
5275
}
5376

54-
public function testDateIntervalNullConversion()
77+
public function testDateIntervalNullConversion() : void
5578
{
5679
self::assertNull($this->type->convertToPHPValue(null, $this->platform));
5780
}
5881

5982
/**
6083
* @group DBAL-1288
6184
*/
62-
public function testRequiresSQLCommentHint()
85+
public function testRequiresSQLCommentHint() : void
6386
{
6487
self::assertTrue($this->type->requiresSQLCommentHint($this->platform));
6588
}
6689

6790
/**
6891
* @dataProvider invalidPHPValuesProvider
69-
*
70-
* @param mixed $value
7192
*/
72-
public function testInvalidTypeConversionToDatabaseValue($value)
93+
public function testInvalidTypeConversionToDatabaseValue($value) : void
7394
{
74-
$this->expectException('Doctrine\DBAL\Types\ConversionException');
95+
$this->expectException(ConversionException::class);
7596

7697
$this->type->convertToDatabaseValue($value, $this->platform);
7798
}
7899

79100
/**
80101
* @return mixed[][]
81102
*/
82-
public function invalidPHPValuesProvider()
103+
public function invalidPHPValuesProvider() : array
83104
{
84105
return [
85106
[0],

0 commit comments

Comments
 (0)