Fix DAY() function with 0<x<1 input (#230)

Also bring support for OpenOffice DATE() calculation method
This commit is contained in:
Maxim 2017-10-04 06:57:01 +03:00 committed by Adrien Crivelli
parent 13265581a9
commit 088a76737e
4 changed files with 64 additions and 25 deletions

View File

@ -1137,10 +1137,14 @@ class DateTime
$dateValue = 1; $dateValue = 1;
} elseif (is_string($dateValue = self::getDateValue($dateValue))) { } elseif (is_string($dateValue = self::getDateValue($dateValue))) {
return Functions::VALUE(); return Functions::VALUE();
} elseif ($dateValue == 0.0) { }
return 0;
} elseif ($dateValue < 0.0) { if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) {
return Functions::NAN(); if ($dateValue < 0.0) {
return Functions::NAN();
} elseif ($dateValue < 1.0) {
return 0;
}
} }
// Execute function // Execute function

View File

@ -165,18 +165,23 @@ class Date
public static function excelToDateTimeObject($excelTimestamp, $timeZone = null) public static function excelToDateTimeObject($excelTimestamp, $timeZone = null)
{ {
$timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone); $timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone);
if ($excelTimestamp < 1.0) { if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) {
// Unix timestamp base date if ($excelTimestamp < 1.0) {
$baseDate = new \DateTime('1970-01-01', $timeZone); // Unix timestamp base date
} else { $baseDate = new \DateTime('1970-01-01', $timeZone);
// MS Excel calendar base dates
if (self::$excelCalendar == self::CALENDAR_WINDOWS_1900) {
// Allow adjustment for 1900 Leap Year in MS Excel
$baseDate = ($excelTimestamp < 60) ? new \DateTime('1899-12-31', $timeZone) : new \DateTime('1899-12-30', $timeZone);
} else { } else {
$baseDate = new \DateTime('1904-01-01', $timeZone); // MS Excel calendar base dates
if (self::$excelCalendar == self::CALENDAR_WINDOWS_1900) {
// Allow adjustment for 1900 Leap Year in MS Excel
$baseDate = ($excelTimestamp < 60) ? new \DateTime('1899-12-31', $timeZone) : new \DateTime('1899-12-30', $timeZone);
} else {
$baseDate = new \DateTime('1904-01-01', $timeZone);
}
} }
} else {
$baseDate = new \DateTime('1899-12-30', $timeZone);
} }
$days = floor($excelTimestamp); $days = floor($excelTimestamp);
$partDay = $excelTimestamp - $days; $partDay = $excelTimestamp - $days;
$hours = floor($partDay * 24); $hours = floor($partDay * 24);
@ -185,7 +190,10 @@ class Date
$partDay = $partDay * 60 - $minutes; $partDay = $partDay * 60 - $minutes;
$seconds = round($partDay * 60); $seconds = round($partDay * 60);
$interval = '+' . $days . ' days'; if ($days >= 0) {
$days = '+' . $days;
}
$interval = $days . ' days';
return $baseDate->modify($interval) return $baseDate->modify($interval)
->setTime($hours, $minutes, $seconds); ->setTime($hours, $minutes, $seconds);

View File

@ -174,12 +174,17 @@ class DateTimeTest extends PHPUnit_Framework_TestCase
/** /**
* @dataProvider providerDAY * @dataProvider providerDAY
* *
* @param mixed $expectedResult * @param mixed $expectedResultExcel
* @param mixed $expectedResultOpenOffice
*/ */
public function testDAY($expectedResult, ...$args) public function testDAY($expectedResultExcel, $expectedResultOpenOffice, ...$args)
{ {
$result = DateTime::DAYOFMONTH(...$args); $resultExcel = DateTime::DAYOFMONTH(...$args);
self::assertEquals($expectedResult, $result, null, 1E-8); self::assertEquals($expectedResultExcel, $resultExcel, null, 1E-8);
Functions::setCompatibilityMode(Functions::COMPATIBILITY_OPENOFFICE);
$resultOpenOffice = DateTime::DAYOFMONTH(...$args);
self::assertEquals($expectedResultOpenOffice, $resultOpenOffice, null, 1E-8);
} }
public function providerDAY() public function providerDAY()

View File

@ -4,31 +4,53 @@
return [ return [
[ [
19, 19, // Result for Excel
19, // Result for OpenOffice
22269, 22269,
], ],
[ [
1, 1, // Result for Excel
1, // Result for OpenOffice
30348, 30348,
], ],
[ [
10, 10, // Result for Excel
10, // Result for OpenOffice
30843, 30843,
], ],
[ [
11, 11, // Result for Excel
11, // Result for OpenOffice
'11-Nov-1918', '11-Nov-1918',
], ],
[ [
28, 28, // Result for Excel
28, // Result for OpenOffice
'28-Feb-1904', '28-Feb-1904',
], ],
[ [
'#VALUE!', '#VALUE!', // Result for Excel
'#VALUE!', // Result for OpenOffice
'Invalid', 'Invalid',
], ],
[ [
'#NUM!', '#NUM!', // Result for Excel
29, // Result for OpenOffice
-1, -1,
], ],
[
1, // Result for Excel
31, // Result for OpenOffice
1,
],
[
0, // Result for Excel
30, // Result for OpenOffice
0.5,
],
[
0, // Result for Excel
30, // Result for OpenOffice
0,
],
]; ];