diff --git a/core/oql/expression.class.inc.php b/core/oql/expression.class.inc.php
index 089a70e71..c7dd8493f 100644
--- a/core/oql/expression.class.inc.php
+++ b/core/oql/expression.class.inc.php
@@ -2762,25 +2762,96 @@ class FunctionExpression extends Expression
return $iRet;
case 'DATE_FORMAT':
- if (count($this->m_aArgs) != 2)
- {
+ if (count($this->m_aArgs) != 2) {
throw new \Exception("Function {$this->m_sVerb} requires 2 arguments");
}
$oDate = new DateTime($this->m_aArgs[0]->Evaluate($aArgs));
- $sFormat = $this->m_aArgs[1]->Evaluate($aArgs);
- $sFormat = str_replace(
- array('%y', '%x', '%w', '%W', '%v', '%T', '%S', '%r', '%p', '%M', '%l', '%k', '%I', '%h', '%b', '%a', '%D', '%c', '%e', '%Y', '%d', '%m', '%H', '%i', '%s'),
- array('y', 'o', 'w', 'l', 'W', 'H:i:s', 's', 'h:i:s A', 'A', 'F', 'g', 'H', 'h', 'h','M', 'D', 'jS', 'n', 'j', 'Y', 'd', 'm', 'H', 'i', 's'),
- $sFormat);
- if (preg_match('/%j/', $sFormat))
- {
- $sFormat = str_replace('%j', date_format($oDate, 'z') + 1, $sFormat);
- }
- if (preg_match('/%[fUuVX]/', $sFormat))
- {
+ $sFormatForMysqlDateFormat = $this->m_aArgs[1]->Evaluate($aArgs);
+
+ if (preg_match('/%[fUuVX]/', $sFormatForMysqlDateFormat)) {
throw new NotYetEvaluatedExpression("Expression ".$this->RenderExpression().' cannot be evaluated (known limitation)');
}
- $sRet = date_format($oDate, $sFormat);
+
+ if (preg_match('/%j/', $sFormatForMysqlDateFormat)) {
+ $sFormatForMysqlDateFormat = str_replace('%j', 'z', $sFormatForMysqlDateFormat);
+ $sRet = date_format($oDate, $sFormatForMysqlDateFormat);
+ $sRet++;
+ /** @noinspection PhpUnnecessaryLocalVariableInspection */
+ $sRet = str_pad($sRet, 3, '0', STR_PAD_LEFT);
+
+ return $sRet;
+ }
+
+ /**
+ * @var string[] $aFormatsForMysqlDateFormat
+ * @link https://dev.mysql.com/doc/refman/5.7/en/date-and-time-functions.html#function_date-format
+ */
+ //@formatter:off we want to keep every single item on its own line to ease comp between MySQL and PHP formats !
+ $aFormatsForMysqlDateFormat = [
+ '%y',
+ '%x',
+ '%w',
+ '%W',
+ '%v',
+ '%T',
+ '%S',
+ '%r',
+ '%p',
+ '%M',
+ '%l',
+ '%k',
+ '%I',
+ '%h',
+ '%b',
+ '%a',
+ '%D',
+ '%c',
+ '%e',
+ '%Y',
+ '%d',
+ '%m',
+ '%H',
+ '%i',
+ '%s'
+ ];
+ //@formatter:on
+ /**
+ * @var string[] $aFormatsForPhpDateFormat
+ * @link https://www.php.net/manual/en/datetime.format.php
+ */
+ //@formatter:off we want to keep every single item on its own line to ease comp between MySQL and PHP formats !
+ $aFormatsForPhpDateFormat = [
+ 'y',
+ 'o',
+ 'w',
+ 'l',
+ 'W',
+ 'H:i:s',
+ 's',
+ 'h:i:s A',
+ 'A',
+ 'F',
+ 'g',
+ 'G',
+ 'h',
+ 'h',
+ 'M',
+ 'D',
+ 'jS',
+ 'n',
+ 'j',
+ 'Y',
+ 'd',
+ 'm',
+ 'H',
+ 'i',
+ 's'
+ ];
+ //@formatter:on
+ $sFormatForPhpDateFormat = str_replace($aFormatsForMysqlDateFormat, $aFormatsForPhpDateFormat, $sFormatForMysqlDateFormat);
+ /** @noinspection PhpUnnecessaryLocalVariableInspection */
+ $sRet = date_format($oDate, $sFormatForPhpDateFormat);
+
return $sRet;
case 'TO_DAYS':
diff --git a/test/core/ExpressionEvaluateTest.php b/test/core/ExpressionEvaluateTest.php
index fa29676fb..8df6d632a 100644
--- a/test/core/ExpressionEvaluateTest.php
+++ b/test/core/ExpressionEvaluateTest.php
@@ -455,7 +455,11 @@ class ExpressionEvaluateTest extends iTopDataTestCase
}
/**
- * Systematically check all supported format specs, for a given date
+ * For a given date,
+ * for all different formats (1st array element returned by {@see static::TimeFormatsProvider}),
+ * compare value returned by :
+ * * DATE_FORMAT() SQL function,
+ * * FunctionExpression('DATE_FORMAT', ...) result
*
* @covers FunctionExpression::Evaluate()
* @dataProvider EveryTimeFormatProvider
@@ -481,7 +485,8 @@ class ExpressionEvaluateTest extends iTopDataTestCase
}
$sSelects = "SELECT ".implode(', ', $aSelects);
$aRes = CMDBSource::QueryToArray($sSelects);
- $aRow = $aRes[0];
+ /** @var array $aMysqlDateFormatRsultsForAllFormats format as key, MySQL evaluated result as value */
+ $aMysqlDateFormatRsultsForAllFormats = $aRes[0];
foreach ($aFormats as $sFormatDesc => $aFormatSpec)
{
$sFormat = $aFormatSpec[0];
@@ -489,13 +494,8 @@ class ExpressionEvaluateTest extends iTopDataTestCase
if ($bProcessed)
{
$oExpression = new FunctionExpression('DATE_FORMAT', array(new ScalarExpression($sDate), new ScalarExpression("%$sFormat")));
- $res = $oExpression->Evaluate(array());
- if (is_numeric($res)) {
- // N°3091 after PHPUnit upgrade from 6 to 8.5 some errors were thrown here
- // example : assertEquals was returning false for expected=8 and actual=08
- $res = (float) $res;
- }
- static::assertEquals($aRow[$sFormat], $res, "Format %$sFormat not matching MySQL for '$sDate'");
+ $itopExpressionResult = $oExpression->Evaluate(array());
+ static::assertSame($aMysqlDateFormatRsultsForAllFormats[$sFormat], $itopExpressionResult, "Format %$sFormat not matching MySQL for '$sDate'");
}
}
}
diff --git a/test/phpunit.xml.dist b/test/phpunit.xml.dist
index 645b6bedd..fa2d9d132 100644
--- a/test/phpunit.xml.dist
+++ b/test/phpunit.xml.dist
@@ -5,6 +5,7 @@
bootstrap="unittestautoload.php"
backupGlobals="true"
colors="true"
+ columns="120"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
@@ -18,8 +19,10 @@
>
-
-
+
+
+
+
diff --git a/test/postbuild_integration.xml.dist b/test/postbuild_integration.xml.dist
index 34aab85da..0a3ce6ef0 100644
--- a/test/postbuild_integration.xml.dist
+++ b/test/postbuild_integration.xml.dist
@@ -17,6 +17,13 @@
verbose="true"
>
+
+
+
+
+
+
+
postbuild_integration