diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 117f2779..0bd131c0 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -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 diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 0c13c0e1..b9f8426f 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -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); diff --git a/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php b/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php index 8959cb00..78ed021f 100644 --- a/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php @@ -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() diff --git a/tests/data/Calculation/DateTime/DAY.php b/tests/data/Calculation/DateTime/DAY.php index 4bcd8e7a..affc4df3 100644 --- a/tests/data/Calculation/DateTime/DAY.php +++ b/tests/data/Calculation/DateTime/DAY.php @@ -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, + ], ];