From 2c981e47a17eee75ef646a177b616a82d445be27 Mon Sep 17 00:00:00 2001 From: Biser Antonov Date: Wed, 11 Jul 2018 15:50:09 +0300 Subject: [PATCH] Added the DAYS() function https://support.office.com/en-us/article/days-function-57740535-d549-4395-8728-0f07bff0b9df --- CHANGELOG.md | 4 + .../Calculation/Calculation.php | 5 + src/PhpSpreadsheet/Calculation/DateTime.php | 48 ++++++++- .../Calculation/functionlist.txt | 1 + .../Calculation/DateTimeTest.php | 16 +++ tests/data/Calculation/DateTime/DAYS.php | 99 +++++++++++++++++++ 6 files changed, 172 insertions(+), 1 deletion(-) create mode 100644 tests/data/Calculation/DateTime/DAYS.php diff --git a/CHANGELOG.md b/CHANGELOG.md index 160f5b4be1..af6832ea2f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased] +### Added + +- Add the DAYS() function - [#594](https://github.com/PHPOffice/PhpSpreadsheet/pull/594) + ### Fixed - Sheet title can contain exclamation mark - [#325](https://github.com/PHPOffice/PhpSpreadsheet/issues/325) diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 34338a6bd2..048490f145 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -650,6 +650,11 @@ class Calculation 'functionCall' => [DateTime::class, 'DAYOFMONTH'], 'argumentCount' => '1', ], + 'DAYS' => [ + 'category' => Category::CATEGORY_DATE_AND_TIME, + 'functionCall' => [DateTime::class, 'DAYS'], + 'argumentCount' => '2', + ], 'DAYS360' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, 'functionCall' => [DateTime::class, 'DAYS360'], diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index a07a28d1a5..844ebd4088 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -70,7 +70,7 @@ public static function getDateValue($dateValue) (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_GNUMERIC)) { return Functions::VALUE(); } - if ((is_object($dateValue)) && ($dateValue instanceof \DateTimeImmutable)) { + if ((is_object($dateValue)) && ($dateValue instanceof \DateTimeInterface)) { $dateValue = Date::PHPToExcel($dateValue); } else { $saveReturnDateType = Functions::getReturnDateType(); @@ -764,6 +764,52 @@ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') return $retVal; } + /** + * DAYS. + * + * Returns the number of days between two dates + * + * Excel Function: + * DAYS(endDate, startDate) + * + * @category Date/Time Functions + * + * @param \DateTimeImmutable|float|int|string $endDate Excel date serial value (float), + * PHP date timestamp (integer), PHP DateTime object, or a standard date string + * @param \DateTimeImmutable|float|int|string $startDate Excel date serial value (float), + * PHP date timestamp (integer), PHP DateTime object, or a standard date string + * + * @return int|string Number of days between start date and end date or an error + */ + public static function DAYS($endDate = 0, $startDate = 0) + { + $startDate = Functions::flattenSingleValue($startDate); + $endDate = Functions::flattenSingleValue($endDate); + + $startDate = self::getDateValue($startDate); + if (is_string($startDate)) { + return Functions::VALUE(); + } + + $endDate = self::getDateValue($endDate); + if (is_string($endDate)) { + return Functions::VALUE(); + } + + // Execute function + $PHPStartDateObject = Date::excelToDateTimeObject($startDate); + $PHPEndDateObject = Date::excelToDateTimeObject($endDate); + + $diff = $PHPStartDateObject->diff($PHPEndDateObject); + $days = $diff->days; + + if ($diff->invert) { + $days = -$days; + } + + return $days; + } + /** * DAYS360. * diff --git a/src/PhpSpreadsheet/Calculation/functionlist.txt b/src/PhpSpreadsheet/Calculation/functionlist.txt index 7043f76906..ee87c17f63 100644 --- a/src/PhpSpreadsheet/Calculation/functionlist.txt +++ b/src/PhpSpreadsheet/Calculation/functionlist.txt @@ -88,6 +88,7 @@ DATEDIF DATEVALUE DAVERAGE DAY +DAYS DAYS360 DB DCOUNT diff --git a/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php b/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php index a6d781a525..0e6711522d 100644 --- a/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/DateTimeTest.php @@ -453,6 +453,22 @@ public function providerDATEDIF() return require 'data/Calculation/DateTime/DATEDIF.php'; } + /** + * @dataProvider providerDAYS + * + * @param mixed $expectedResult + */ + public function testDAYS($expectedResult, ...$args) + { + $result = DateTime::DAYS(...$args); + self::assertEquals($expectedResult, $result, null, 1E-8); + } + + public function providerDAYS() + { + return require 'data/Calculation/DateTime/DAYS.php'; + } + /** * @dataProvider providerDAYS360 * diff --git a/tests/data/Calculation/DateTime/DAYS.php b/tests/data/Calculation/DateTime/DAYS.php new file mode 100644 index 0000000000..074fc302cd --- /dev/null +++ b/tests/data/Calculation/DateTime/DAYS.php @@ -0,0 +1,99 @@ +