Unverified Commit 755c99e3 authored by Sergei Morozov's avatar Sergei Morozov Committed by GitHub

Merge pull request #3108 from morozov/get-date-diff-expression

Fixed inconsistency in calculating date difference between platforms
parents e4af109a eb523ed4
...@@ -160,14 +160,10 @@ class OraclePlatform extends AbstractPlatform ...@@ -160,14 +160,10 @@ class OraclePlatform extends AbstractPlatform
/** /**
* {@inheritDoc} * {@inheritDoc}
*
* Note: Since Oracle timestamp differences are calculated down to the microsecond we have to truncate
* them to the difference in days. This is obviously a restriction of the original functionality, but we
* need to make this a portable function.
*/ */
public function getDateDiffExpression($date1, $date2) public function getDateDiffExpression($date1, $date2)
{ {
return "TRUNC(TO_NUMBER(SUBSTR((" . $date1 . "-" . $date2 . "), 1, INSTR(" . $date1 . "-" . $date2 .", ' '))))"; return sprintf('TRUNC(%s) - TRUNC(%s)', $date1, $date2);
} }
/** /**
......
...@@ -174,7 +174,7 @@ class SqlitePlatform extends AbstractPlatform ...@@ -174,7 +174,7 @@ class SqlitePlatform extends AbstractPlatform
*/ */
public function getDateDiffExpression($date1, $date2) public function getDateDiffExpression($date1, $date2)
{ {
return 'ROUND(JULIANDAY('.$date1 . ')-JULIANDAY('.$date2.'))'; return sprintf("JULIANDAY(%s, 'start of day') - JULIANDAY(%s, 'start of day')", $date1, $date2);
} }
/** /**
......
...@@ -5,7 +5,6 @@ namespace Doctrine\Tests\DBAL\Functional; ...@@ -5,7 +5,6 @@ namespace Doctrine\Tests\DBAL\Functional;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\FetchMode; use Doctrine\DBAL\FetchMode;
use Doctrine\DBAL\ParameterType; use Doctrine\DBAL\ParameterType;
use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Platforms\TrimMode; use Doctrine\DBAL\Platforms\TrimMode;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use const CASE_LOWER; use const CASE_LOWER;
...@@ -531,7 +530,6 @@ class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -531,7 +530,6 @@ class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase
{ {
$p = $this->_conn->getDatabasePlatform(); $p = $this->_conn->getDatabasePlatform();
$sql = 'SELECT '; $sql = 'SELECT ';
$sql .= $p->getDateDiffExpression('test_datetime', $p->getCurrentTimestampSQL()) .' AS diff, ';
$sql .= $p->getDateAddSecondsExpression('test_datetime', 1) .' AS add_seconds, '; $sql .= $p->getDateAddSecondsExpression('test_datetime', 1) .' AS add_seconds, ';
$sql .= $p->getDateSubSecondsExpression('test_datetime', 1) .' AS sub_seconds, '; $sql .= $p->getDateSubSecondsExpression('test_datetime', 1) .' AS sub_seconds, ';
$sql .= $p->getDateAddMinutesExpression('test_datetime', 5) .' AS add_minutes, '; $sql .= $p->getDateAddMinutesExpression('test_datetime', 5) .' AS add_minutes, ';
...@@ -553,8 +551,6 @@ class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -553,8 +551,6 @@ class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase
$row = $this->_conn->fetchAssoc($sql); $row = $this->_conn->fetchAssoc($sql);
$row = array_change_key_case($row, CASE_LOWER); $row = array_change_key_case($row, CASE_LOWER);
$diff = (strtotime('2010-01-01') - strtotime(date('Y-m-d'))) / 3600 / 24;
self::assertEquals($diff, $row['diff'], "Date difference should be approx. ".$diff." days.", 1);
self::assertEquals('2010-01-01 10:10:11', date('Y-m-d H:i:s', strtotime($row['add_seconds'])), "Adding second should end up on 2010-01-01 10:10:11"); self::assertEquals('2010-01-01 10:10:11', date('Y-m-d H:i:s', strtotime($row['add_seconds'])), "Adding second should end up on 2010-01-01 10:10:11");
self::assertEquals('2010-01-01 10:10:09', date('Y-m-d H:i:s', strtotime($row['sub_seconds'])), "Subtracting second should end up on 2010-01-01 10:10:09"); self::assertEquals('2010-01-01 10:10:09', date('Y-m-d H:i:s', strtotime($row['sub_seconds'])), "Subtracting second should end up on 2010-01-01 10:10:09");
self::assertEquals('2010-01-01 10:15:10', date('Y-m-d H:i:s', strtotime($row['add_minutes'])), "Adding minutes should end up on 2010-01-01 10:15:10"); self::assertEquals('2010-01-01 10:15:10', date('Y-m-d H:i:s', strtotime($row['add_minutes'])), "Adding minutes should end up on 2010-01-01 10:15:10");
......
<?php
namespace Doctrine\Tests\DBAL\Functional\Platform;
use DateTimeImmutable;
use Doctrine\DBAL\Schema\Table;
use Doctrine\Tests\DbalFunctionalTestCase;
use function sprintf;
class DateExpressionTest extends DbalFunctionalTestCase
{
/**
* @dataProvider differenceProvider
*/
public function testDifference(string $date1, string $date2, int $expected) : void
{
$table = new Table('date_expr_test');
$table->addColumn('date1', 'date');
$table->addColumn('date2', 'date');
$this->_conn->getSchemaManager()->dropAndCreateTable($table);
$this->_conn->insert('date_expr_test', [
'date1' => $date1,
'date2' => $date2,
]);
$platform = $this->_conn->getDatabasePlatform();
$sql = sprintf('SELECT %s FROM date_expr_test', $platform->getDateDiffExpression('date1', 'date2'));
$diff = $this->_conn->query($sql)->fetchColumn();
self::assertEquals($expected, $diff);
}
/**
* @return string[][]|int[][]
*/
public static function differenceProvider() : iterable
{
$date1 = new DateTimeImmutable();
$date2 = new DateTimeImmutable('2018-04-10 10:10:10');
$expected = $date1->modify('midnight')->diff(
$date2->modify('midnight')
)->days;
return [
'dynamic' => [
$date1->format('Y-m-d H:i:s'),
$date2->format('Y-m-d H:i:s'),
$expected,
],
'same day' => ['2018-04-14 23:59:59', '2018-04-14 00:00:00', 0],
'midnight' => ['2018-04-14 00:00:00', '2018-04-13 23:59:59', 1],
];
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment