From 1e59b9113f59ac42c2d2dac8b6e680537f53f69c Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Thu, 10 Feb 2022 18:15:09 +0100 Subject: [PATCH] Last of the work on array-enabling Date/Time functions; all completed in this category --- phpstan-baseline.neon | 15 --------- src/PhpSpreadsheet/Calculation/DateTime.php | 20 ++++++------ .../Calculation/DateTimeExcel/Days360.php | 2 +- .../Calculation/DateTimeExcel/Difference.php | 16 ++++++++-- .../Calculation/DateTimeExcel/Month.php | 27 +++++++++++++--- .../Calculation/DateTimeExcel/NetworkDays.php | 19 ++++++++++-- .../Calculation/DateTimeExcel/WorkDay.php | 6 ++-- .../Calculation/DateTimeExcel/YearFrac.php | 26 +++++++++++----- src/PhpSpreadsheet/Calculation/Functions.php | 18 +++++++++++ .../Functions/DateTime/DateDifTest.php | 28 +++++++++++++++++ .../Functions/DateTime/EDateTest.php | 25 +++++++++++++++ .../Functions/DateTime/EoMonthTest.php | 25 +++++++++++++++ .../Functions/DateTime/NetworkDaysTest.php | 31 +++++++++++++++++++ .../Functions/DateTime/YearFracTest.php | 28 +++++++++++++++++ 14 files changed, 242 insertions(+), 44 deletions(-) diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index 25f0fc47..b7ca9291 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -575,21 +575,6 @@ parameters: count: 1 path: src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeValue.php - - - message: "#^Binary operation \"/\" between int\\|string and \\(float\\|int\\) results in an error\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php - - - - message: "#^Binary operation \"/\" between int\\|string and 360 results in an error\\.$#" - count: 3 - path: src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php - - - - message: "#^Binary operation \"/\" between int\\|string and 365 results in an error\\.$#" - count: 1 - path: src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php - - message: "#^Method PhpOffice\\\\PhpSpreadsheet\\\\Calculation\\\\Engine\\\\Logger\\:\\:writeDebugLog\\(\\) has parameter \\$args with no type specified\\.$#" count: 1 diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 7cff25a7..79fa8dc0 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -278,9 +278,9 @@ class DateTime * or a standard date string * @param mixed $endDate Excel date serial value, PHP date/time stamp, PHP DateTime object * or a standard date string - * @param string $unit + * @param array|string $unit * - * @return int|string Interval between the dates + * @return array|int|string Interval between the dates */ public static function DATEDIF($startDate = 0, $endDate = 0, $unit = 'D') { @@ -300,12 +300,12 @@ class DateTime * @See DateTimeExcel\Days::between() * Use the between method in the DateTimeExcel\Days class instead * - * @param DateTimeInterface|float|int|string $endDate Excel date serial value (float), + * @param array|DateTimeInterface|float|int|string $endDate Excel date serial value (float), * PHP date timestamp (integer), PHP DateTime object, or a standard date string - * @param DateTimeInterface|float|int|string $startDate Excel date serial value (float), + * @param array|DateTimeInterface|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 + * @return array|int|string Number of days between start date and end date or an error */ public static function DAYS($endDate = 0, $startDate = 0) { @@ -331,7 +331,7 @@ class DateTime * PHP DateTime object, or a standard date string * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string - * @param bool $method US or European Method + * @param array|bool $method US or European Method * FALSE or omitted: U.S. (NASD) method. If the starting date is * the last day of a month, it becomes equal to the 30th of the * same month. If the ending date is the last day of a month and @@ -343,7 +343,7 @@ class DateTime * occur on the 31st of a month become equal to the 30th of the * same month. * - * @return int|string Number of days between start date and end date + * @return array|int|string Number of days between start date and end date */ public static function DAYS360($startDate = 0, $endDate = 0, $method = false) { @@ -373,14 +373,14 @@ class DateTime * PHP DateTime object, or a standard date string * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string - * @param int $method Method used for the calculation + * @param array|int $method Method used for the calculation * 0 or omitted US (NASD) 30/360 * 1 Actual/actual * 2 Actual/360 * 3 Actual/365 * 4 European 30/360 * - * @return float|string fraction of the year, or a string containing an error + * @return array|float|string fraction of the year, or a string containing an error */ public static function YEARFRAC($startDate = 0, $endDate = 0, $method = 0) { @@ -409,7 +409,7 @@ class DateTime * PHP DateTime object, or a standard date string * @param mixed $dateArgs * - * @return int|string Interval between the dates + * @return array|int|string Interval between the dates */ public static function NETWORKDAYS($startDate, $endDate, ...$dateArgs) { diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days360.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days360.php index 50af5c80..2220aaee 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days360.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Days360.php @@ -46,7 +46,7 @@ class Days360 */ public static function between($startDate = 0, $endDate = 0, $method = false) { - if (is_array($endDate) || is_array($startDate) || is_array($method)) { + if (is_array($startDate) || is_array($endDate) || is_array($method)) { return self::evaluateArrayArguments([self::class, __FUNCTION__], $startDate, $endDate, $method); } diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Difference.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Difference.php index 6adeca17..1f4812f2 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Difference.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Difference.php @@ -4,25 +4,37 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel; use DateInterval; use DateTime; +use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled; use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper; class Difference { + use ArrayEnabled; + /** * DATEDIF. * * @param mixed $startDate Excel date serial value, PHP date/time stamp, PHP DateTime object * or a standard date string + * Or can be an array of date values * @param mixed $endDate Excel date serial value, PHP date/time stamp, PHP DateTime object * or a standard date string - * @param string $unit + * Or can be an array of date values + * @param array|string $unit + * Or can be an array of unit values * - * @return int|string Interval between the dates + * @return array|int|string Interval between the dates + * If an array of values is passed for the $startDate or $endDays,arguments, then the returned result + * will also be an array with matching dimensions */ public static function interval($startDate, $endDate, $unit = 'D') { + if (is_array($startDate) || is_array($endDate) || is_array($unit)) { + return self::evaluateArrayArguments([self::class, __FUNCTION__], $startDate, $endDate, $unit); + } + try { $startDate = Helpers::getDateValue($startDate); $endDate = Helpers::getDateValue($endDate); diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php index 560b7a80..c72d006b 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php @@ -2,10 +2,13 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel; +use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled; use PhpOffice\PhpSpreadsheet\Calculation\Exception; class Month { + use ArrayEnabled; + /** * EDATE. * @@ -19,15 +22,23 @@ class Month * * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string - * @param int $adjustmentMonths The number of months before or after start_date. + * Or can be an array of date values + * @param array|int $adjustmentMonths The number of months before or after start_date. * A positive value for months yields a future date; * a negative value yields a past date. + * Or can be an array of adjustment values * - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * @return array|mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, * depending on the value of the ReturnDateType flag + * If an array of values is passed as the argument, then the returned result will also be an array + * with the same dimensions */ public static function adjust($dateValue, $adjustmentMonths) { + if (is_array($dateValue) || is_array($adjustmentMonths)) { + return self::evaluateArrayArguments([self::class, __FUNCTION__], $dateValue, $adjustmentMonths); + } + try { $dateValue = Helpers::getDateValue($dateValue, false); $adjustmentMonths = Helpers::validateNumericNull($adjustmentMonths); @@ -54,15 +65,23 @@ class Month * * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string - * @param int $adjustmentMonths The number of months before or after start_date. + * Or can be an array of date values + * @param array|int $adjustmentMonths The number of months before or after start_date. * A positive value for months yields a future date; * a negative value yields a past date. + * Or can be an array of adjustment values * - * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * @return array|mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, * depending on the value of the ReturnDateType flag + * If an array of values is passed as the argument, then the returned result will also be an array + * with the same dimensions */ public static function lastDay($dateValue, $adjustmentMonths) { + if (is_array($dateValue) || is_array($adjustmentMonths)) { + return self::evaluateArrayArguments([self::class, __FUNCTION__], $dateValue, $adjustmentMonths); + } + try { $dateValue = Helpers::getDateValue($dateValue, false); $adjustmentMonths = Helpers::validateNumericNull($adjustmentMonths); diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php index d0f53cf3..9a87af27 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php @@ -2,11 +2,14 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel; +use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled; use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Functions; class NetworkDays { + use ArrayEnabled; + /** * NETWORKDAYS. * @@ -20,14 +23,26 @@ class NetworkDays * * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string + * Or can be an array of date values * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string - * @param mixed $dateArgs + * Or can be an array of date values + * @param mixed $dateArgs An array of dates (such as holidays) to exclude from the calculation * - * @return int|string Interval between the dates + * @return array|int|string Interval between the dates */ public static function count($startDate, $endDate, ...$dateArgs) { + if (is_array($startDate) || is_array($endDate)) { + return self::evaluateArrayArgumentsSubset( + [self::class, __FUNCTION__], + 2, + $startDate, + $endDate, + ...$dateArgs + ); + } + try { // Retrieve the mandatory start and end date that are referenced in the function definition $sDate = Helpers::getDateValue($startDate); diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php index 0da442af..1f5735e8 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php @@ -28,7 +28,7 @@ class WorkDay * startDate. A positive value for days yields a future date; a * negative value yields a past date. * Or can be an array of int values - * @param mixed $dateArgs + * @param null|mixed $dateArgs An array of dates (such as holidays) to exclude from the calculation * * @return array|mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, * depending on the value of the ReturnDateType flag @@ -194,8 +194,8 @@ class WorkDay private static function getWeekDay(float $date, int $wd): int { - $result = Week::day($date, $wd); + $result = Functions::scalar(Week::day($date, $wd)); - return is_string($result) ? -1 : $result; + return is_int($result) ? $result : -1; } } diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php index da2ac12f..6babf633 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php @@ -2,12 +2,15 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel; +use PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled; use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper; class YearFrac { + use ArrayEnabled; + /** * YEARFRAC. * @@ -23,19 +26,28 @@ class YearFrac * * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string + * Or can be an array of methods * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string - * @param int $method Method used for the calculation + * Or can be an array of methods + * @param array|int $method Method used for the calculation * 0 or omitted US (NASD) 30/360 * 1 Actual/actual * 2 Actual/360 * 3 Actual/365 * 4 European 30/360 + * Or can be an array of methods * - * @return float|string fraction of the year, or a string containing an error + * @return array|float|string fraction of the year, or a string containing an error + * If an array of values is passed for the $startDate or $endDays,arguments, then the returned result + * will also be an array with matching dimensions */ public static function fraction($startDate, $endDate, $method = 0) { + if (is_array($startDate) || is_array($endDate) || is_array($method)) { + return self::evaluateArrayArguments([self::class, __FUNCTION__], $startDate, $endDate, $method); + } + try { $method = (int) Helpers::validateNumericNull($method); $sDate = Helpers::getDateValue($startDate); @@ -50,15 +62,15 @@ class YearFrac switch ($method) { case 0: - return Days360::between($startDate, $endDate) / 360; + return Functions::scalar(Days360::between($startDate, $endDate)) / 360; case 1: return self::method1($startDate, $endDate); case 2: - return Difference::interval($startDate, $endDate) / 360; + return Functions::scalar(Difference::interval($startDate, $endDate)) / 360; case 3: - return Difference::interval($startDate, $endDate) / 365; + return Functions::scalar(Difference::interval($startDate, $endDate)) / 365; case 4: - return Days360::between($startDate, $endDate, true) / 360; + return Functions::scalar(Days360::between($startDate, $endDate, true)) / 360; } return Functions::NAN(); @@ -87,7 +99,7 @@ class YearFrac private static function method1(float $startDate, float $endDate): float { - $days = Difference::interval($startDate, $endDate); + $days = Functions::scalar(Difference::interval($startDate, $endDate)); $startYear = (int) DateParts::year($startDate); $endYear = (int) DateParts::year($endDate); $years = $endYear - $startYear + 1; diff --git a/src/PhpSpreadsheet/Calculation/Functions.php b/src/PhpSpreadsheet/Calculation/Functions.php index 75d4582b..0ccf72e9 100644 --- a/src/PhpSpreadsheet/Calculation/Functions.php +++ b/src/PhpSpreadsheet/Calculation/Functions.php @@ -608,6 +608,24 @@ class Functions return $arrayValues; } + /** + * @param mixed $value + * + * @return null|mixed + */ + public static function scalar($value) + { + if (!is_array($value)) { + return $value; + } + + do { + $value = array_pop($value); + } while (is_array($value)); + + return $value; + } + /** * Convert a multi-dimensional array to a simple 1-dimensional array, but retain an element of indexing. * diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php index d7d69376..77af98ee 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/DateDifTest.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use PhpOffice\PhpSpreadsheet\Calculation\Calculation; + class DateDifTest extends AllSetupTeardown { /** @@ -22,4 +24,30 @@ class DateDifTest extends AllSetupTeardown { return require 'tests/data/Calculation/DateTime/DATEDIF.php'; } + + /** + * @dataProvider providerDateDifArray + */ + public function testDateDifArray(array $expectedResult, string $startDate, string $endDate, ?string $methods): void + { + $calculation = Calculation::getInstance(); + + if ($methods === null) { + $formula = "=DATEDIF({$startDate}, {$endDate})"; + } else { + $formula = "=DATEDIF({$startDate}, {$endDate}, {$methods})"; + } + $result = $calculation->_calculateFormulaValue($formula); + self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + } + + public function providerDateDifArray(): array + { + return [ + 'row vector #1' => [[[364, 202, '#NUM!']], '{"2022-01-01", "2022-06-12", "2023-07-22"}', '"2022-12-31"', null], + 'column vector #1' => [[[364], [362], [359]], '{"2022-01-01"; "2022-01-03"; "2022-01-06"}', '"2022-12-31"', null], + 'matrix #1' => [[[365, 266], [139, 1]], '{"2022-01-01", "2022-04-10"; "2022-08-15", "2022-12-31"}', '"2023-01-01"', null], + 'column vector with methods' => [[[364, 11], [242, 7], [173, 5]], '{"2022-01-01"; "2022-05-03"; "2022-07-11"}', '"2022-12-31"', '{"D", "M"}'], + ]; + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php index 22613fe5..5b8479cb 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EDateTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Month; class EDateTest extends AllSetupTeardown @@ -46,4 +47,28 @@ class EDateTest extends AllSetupTeardown // ... with the correct value self::assertEquals($result->format('d-M-Y'), '26-Dec-2011'); } + + /** + * @dataProvider providerEDateArray + */ + public function testEDateArray(array $expectedResult, string $dateValues, string $methods): void + { + $calculation = Calculation::getInstance(); + + $formula = "=EDATE({$dateValues}, {$methods})"; + $result = $calculation->_calculateFormulaValue($formula); + self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + } + + public function providerEDateArray(): array + { + return [ + 'row vector #1' => [[[44593, 44632, 45337]], '{"2022-01-01", "2022-02-12", "2024-01-15"}', '1'], + 'column vector #1' => [[[44593], [44632], [45337]], '{"2022-01-01"; "2022-02-12"; "2024-01-15"}', '1'], + 'matrix #1' => [[[44593, 44632], [44652, 45343]], '{"2022-01-01", "2022-02-12"; "2022-03-01", "2024-01-21"}', '1'], + 'row vector #2' => [[[44573, 44604, 44632]], '"2022-02-12"', '{-1, 0, 1}'], + 'column vector #2' => [[[44573], [44604], [44632]], '"2022-02-12"', '{-1; 0; 1}'], + 'matrix #2' => [[[44573, 44604], [44632, 45334]], '"2022-02-12"', '{-1, 0; 1, 24}'], + ]; + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php index 3c39fbbc..935b3cbc 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/EoMonthTest.php @@ -2,6 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Month; class EoMonthTest extends AllSetupTeardown @@ -45,4 +46,28 @@ class EoMonthTest extends AllSetupTeardown // ... with the correct value self::assertSame($result->format('d-M-Y'), '31-Dec-2011'); } + + /** + * @dataProvider providerEoMonthArray + */ + public function testEoMonthArray(array $expectedResult, string $dateValues, string $methods): void + { + $calculation = Calculation::getInstance(); + + $formula = "=EOMONTH({$dateValues}, {$methods})"; + $result = $calculation->_calculateFormulaValue($formula); + self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + } + + public function providerEoMonthArray(): array + { + return [ + 'row vector #1' => [[[44620, 44651, 45351]], '{"2022-01-01", "2022-02-12", "2024-01-15"}', '1'], + 'column vector #1' => [[[44620], [44651], [45351]], '{"2022-01-01"; "2022-02-12"; "2024-01-15"}', '1'], + 'matrix #1' => [[[44620, 44651], [44681, 45351]], '{"2022-01-01", "2022-02-12"; "2022-03-01", "2024-01-21"}', '1'], + 'row vector #2' => [[[44592, 44620, 44651]], '"2022-02-12"', '{-1, 0, 1}'], + 'column vector #2' => [[[44592], [44620], [44651]], '"2022-02-12"', '{-1; 0; 1}'], + 'matrix #2' => [[[44592, 44620], [44651, 45351]], '"2022-02-12"', '{-1, 0; 1, 24}'], + ]; + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/NetworkDaysTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/NetworkDaysTest.php index d6b1a89f..d5378b35 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/NetworkDaysTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/NetworkDaysTest.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use PhpOffice\PhpSpreadsheet\Calculation\Calculation; + class NetworkDaysTest extends AllSetupTeardown { /** @@ -49,4 +51,33 @@ class NetworkDaysTest extends AllSetupTeardown { return require 'tests/data/Calculation/DateTime/NETWORKDAYS.php'; } + + /** + * @dataProvider providerNetWorkDaysArray + */ + public function testNetWorkDaysArray(array $expectedResult, string $startDate, string $endDays, ?string $holidays): void + { + $calculation = Calculation::getInstance(); + + if ($holidays === null) { + $formula = "=NETWORKDAYS({$startDate}, {$endDays})"; + } else { + $formula = "=NETWORKDAYS({$startDate}, {$endDays}, {$holidays})"; + } + $result = $calculation->_calculateFormulaValue($formula); + self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + } + + public function providerNetWorkDaysArray(): array + { + return [ + 'row vector #1' => [[[234, 233, 232]], '{"2022-02-01", "2022-02-02", "2022-02-03"}', '"2022-12-25"', null], + 'column vector #1' => [[[234], [233], [232]], '{"2022-02-01"; "2022-02-02"; "2022-02-03"}', '"2022-12-25"', null], + 'matrix #1' => [[[234, 233], [232, 231]], '{"2022-02-01", "2022-02-02"; "2022-02-03", "2022-02-04"}', '"2022-12-25"', null], + 'row vector #2' => [[[234, -27]], '"2022-02-01"', '{"2022-12-25", "2021-12-25"}', null], + 'column vector #2' => [[[234], [-27]], '"2022-02-01"', '{"2022-12-25"; "2021-12-25"}', null], + 'row vector with Holiday' => [[[233, -27]], '"2022-02-01"', '{"2022-12-25", "2021-12-25"}', '{"2022-02-02"}'], + 'row vector with Holidays' => [[[232, -27]], '"2022-02-01"', '{"2022-12-25", "2021-12-25"}', '{"2022-02-02", "2022-02-03"}'], + ]; + } } diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearFracTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearFracTest.php index d7427bfd..9c78fbbe 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearFracTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/YearFracTest.php @@ -2,6 +2,8 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; +use PhpOffice\PhpSpreadsheet\Calculation\Calculation; + class YearFracTest extends AllSetupTeardown { /** @@ -41,4 +43,30 @@ class YearFracTest extends AllSetupTeardown { return require 'tests/data/Calculation/DateTime/YEARFRAC.php'; } + + /** + * @dataProvider providerYearFracArray + */ + public function testYearFracArray(array $expectedResult, string $startDate, string $endDate, ?string $methods): void + { + $calculation = Calculation::getInstance(); + + if ($methods === null) { + $formula = "=YEARFRAC({$startDate}, {$endDate})"; + } else { + $formula = "=YEARFRAC({$startDate}, {$endDate}, {$methods})"; + } + $result = $calculation->_calculateFormulaValue($formula); + self::assertEqualsWithDelta($expectedResult, $result, 1.0e-14); + } + + public function providerYearFracArray(): array + { + return [ + 'row vector #1' => [[[1.0, 0.55277777777778, 0.56111111111111]], '{"2022-01-01", "2022-06-12", "2023-07-22"}', '"2022-12-31"', null], + 'column vector #1' => [[[1.0], [0.99444444444445], [0.98611111111111]], '{"2022-01-01"; "2022-01-03"; "2022-01-06"}', '"2022-12-31"', null], + 'matrix #1' => [[[0.002777777777778, 0.027777777777778], [0.625, 1.0]], '{"2022-01-01", "2022-01-10"; "2022-08-15", "2022-12-31"}', '"2021-12-31"', null], + 'column vector with methods' => [[[0.99726027397260, 0.99722222222222], [0.99178082191781, 0.99166666666667], [0.98356164383562, 0.98333333333333]], '{"2022-01-01"; "2022-01-03"; "2022-01-06"}', '"2022-12-31"', '{1, 4}'], + ]; + } }