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;
} elseif (is_string($dateValue = self::getDateValue($dateValue))) {
return Functions::VALUE();
} elseif ($dateValue == 0.0) {
return 0;
} elseif ($dateValue < 0.0) {
return Functions::NAN();
}
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) {
if ($dateValue < 0.0) {
return Functions::NAN();
} elseif ($dateValue < 1.0) {
return 0;
}
}
// Execute function

View File

@ -165,18 +165,23 @@ class Date
public static function excelToDateTimeObject($excelTimestamp, $timeZone = null)
{
$timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone);
if ($excelTimestamp < 1.0) {
// Unix timestamp base date
$baseDate = new \DateTime('1970-01-01', $timeZone);
} else {
// 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);
if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) {
if ($excelTimestamp < 1.0) {
// Unix timestamp base date
$baseDate = new \DateTime('1970-01-01', $timeZone);
} 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);
$partDay = $excelTimestamp - $days;
$hours = floor($partDay * 24);
@ -185,7 +190,10 @@ class Date
$partDay = $partDay * 60 - $minutes;
$seconds = round($partDay * 60);
$interval = '+' . $days . ' days';
if ($days >= 0) {
$days = '+' . $days;
}
$interval = $days . ' days';
return $baseDate->modify($interval)
->setTime($hours, $minutes, $seconds);

View File

@ -174,12 +174,17 @@ class DateTimeTest extends PHPUnit_Framework_TestCase
/**
* @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);
self::assertEquals($expectedResult, $result, null, 1E-8);
$resultExcel = DateTime::DAYOFMONTH(...$args);
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()

View File

@ -4,31 +4,53 @@
return [
[
19,
19, // Result for Excel
19, // Result for OpenOffice
22269,
],
[
1,
1, // Result for Excel
1, // Result for OpenOffice
30348,
],
[
10,
10, // Result for Excel
10, // Result for OpenOffice
30843,
],
[
11,
11, // Result for Excel
11, // Result for OpenOffice
'11-Nov-1918',
],
[
28,
28, // Result for Excel
28, // Result for OpenOffice
'28-Feb-1904',
],
[
'#VALUE!',
'#VALUE!', // Result for Excel
'#VALUE!', // Result for OpenOffice
'Invalid',
],
[
'#NUM!',
'#NUM!', // Result for Excel
29, // Result for OpenOffice
-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,
],
];