From cd667500e086b1e4fdcc4001f5cc1a4eb4a9fbd4 Mon Sep 17 00:00:00 2001 From: MarkBaker Date: Wed, 12 May 2021 13:25:28 +0200 Subject: [PATCH] Group some of the newly extracted Excel DateTime function implementations into groups of related functions with appropriate and meaningful class names, and rename the public methods to be more descriptive of their purpose --- .../Calculation/Calculation.php | 22 +-- src/PhpSpreadsheet/Calculation/DateTime.php | 66 ++++----- .../DateTimeExcel/{Now.php => Current.php} | 29 +++- .../Calculation/DateTimeExcel/DateParts.php | 127 +++++++++++++++++ .../Calculation/DateTimeExcel/Day.php | 65 --------- .../Calculation/DateTimeExcel/Hour.php | 44 ------ .../Calculation/DateTimeExcel/IsoWeekNum.php | 59 -------- .../Calculation/DateTimeExcel/Minute.php | 44 ------ .../Calculation/DateTimeExcel/Month.php | 40 ------ .../Calculation/DateTimeExcel/NetworkDays.php | 6 +- .../Calculation/DateTimeExcel/Second.php | 44 ------ .../Calculation/DateTimeExcel/TimeParts.php | 112 +++++++++++++++ .../Calculation/DateTimeExcel/Today.php | 34 ----- .../DateTimeExcel/{WeekNum.php => Week.php} | 132 +++++++++++++++++- .../Calculation/DateTimeExcel/WeekDay.php | 83 ----------- .../Calculation/DateTimeExcel/WorkDay.php | 2 +- .../Calculation/DateTimeExcel/Year.php | 40 ------ .../Calculation/DateTimeExcel/YearFrac.php | 14 +- .../Calculation/Financial/Amortization.php | 2 +- .../Calculation/Financial/Coupons.php | 6 +- .../Financial/Securities/Price.php | 2 +- .../Financial/Securities/Yields.php | 4 +- .../Calculation/Financial/TreasuryBill.php | 6 +- .../Functions/DateTime/WeekDayTest.php | 8 +- 24 files changed, 463 insertions(+), 528 deletions(-) rename src/PhpSpreadsheet/Calculation/DateTimeExcel/{Now.php => Current.php} (51%) create mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/DateParts.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/Day.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/Hour.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/IsoWeekNum.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/Minute.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/Second.php create mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeParts.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/Today.php rename src/PhpSpreadsheet/Calculation/DateTimeExcel/{WeekNum.php => Week.php} (55%) delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/WeekDay.php delete mode 100644 src/PhpSpreadsheet/Calculation/DateTimeExcel/Year.php diff --git a/src/PhpSpreadsheet/Calculation/Calculation.php b/src/PhpSpreadsheet/Calculation/Calculation.php index 54d9a6e8..52dd290c 100644 --- a/src/PhpSpreadsheet/Calculation/Calculation.php +++ b/src/PhpSpreadsheet/Calculation/Calculation.php @@ -778,7 +778,7 @@ class Calculation ], 'DAY' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Day::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\DateParts::class, 'day'], 'argumentCount' => '1', ], 'DAYS' => [ @@ -1240,7 +1240,7 @@ class Calculation ], 'HOUR' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Hour::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\TimeParts::class, 'hour'], 'argumentCount' => '1', ], 'HYPERLINK' => [ @@ -1504,7 +1504,7 @@ class Calculation ], 'ISOWEEKNUM' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\IsoWeekNum::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\Week::class, 'isoWeekNumber'], 'argumentCount' => '1', ], 'ISPMT' => [ @@ -1684,7 +1684,7 @@ class Calculation ], 'MINUTE' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Minute::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\TimeParts::class, 'minute'], 'argumentCount' => '1', ], 'MINVERSE' => [ @@ -1724,7 +1724,7 @@ class Calculation ], 'MONTH' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Month::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\DateParts::class, 'month'], 'argumentCount' => '1', ], 'MROUND' => [ @@ -1824,7 +1824,7 @@ class Calculation ], 'NOW' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Now::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\Current::class, 'now'], 'argumentCount' => '0', ], 'NPER' => [ @@ -2178,7 +2178,7 @@ class Calculation ], 'SECOND' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Second::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\TimeParts::class, 'second'], 'argumentCount' => '1', ], 'SEQUENCE' => [ @@ -2449,7 +2449,7 @@ class Calculation ], 'TODAY' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Today::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\Current::class, 'today'], 'argumentCount' => '0', ], 'TRANSPOSE' => [ @@ -2574,12 +2574,12 @@ class Calculation ], 'WEEKDAY' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\WeekDay::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\Week::class, 'day'], 'argumentCount' => '1,2', ], 'WEEKNUM' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\WeekNum::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\Week::class, 'number'], 'argumentCount' => '1,2', ], 'WEIBULL' => [ @@ -2629,7 +2629,7 @@ class Calculation ], 'YEAR' => [ 'category' => Category::CATEGORY_DATE_AND_TIME, - 'functionCall' => [DateTimeExcel\Year::class, 'evaluate'], + 'functionCall' => [DateTimeExcel\DateParts::class, 'year'], 'argumentCount' => '1', ], 'YEARFRAC' => [ diff --git a/src/PhpSpreadsheet/Calculation/DateTime.php b/src/PhpSpreadsheet/Calculation/DateTime.php index 4959c957..a81190d4 100644 --- a/src/PhpSpreadsheet/Calculation/DateTime.php +++ b/src/PhpSpreadsheet/Calculation/DateTime.php @@ -63,15 +63,15 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Now::evaluate() - * Use the evaluate method in the DateTimeExcel\Now class instead + * @See DateTimeExcel\Current::now() + * Use the now method in the DateTimeExcel\Current class instead * * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, * depending on the value of the ReturnDateType flag */ public static function DATETIMENOW() { - return DateTimeExcel\Now::evaluate(); + return DateTimeExcel\Current::now(); } /** @@ -90,15 +90,15 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Today::evaluate() - * Use the evaluate method in the DateTimeExcel\Today class instead + * @See DateTimeExcel\Current::today() + * Use the today method in the DateTimeExcel\Current class instead * * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, * depending on the value of the ReturnDateType flag */ public static function DATENOW() { - return DateTimeExcel\Today::evaluate(); + return DateTimeExcel\Current::today(); } /** @@ -458,8 +458,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Day::evaluate() - * Use the evaluate method in the DateTimeExcel\Day class instead + * @See DateTimeExcel\DateParts::day() + * Use the day method in the DateTimeExcel\DateParts class instead * * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string @@ -468,7 +468,7 @@ class DateTime */ public static function DAYOFMONTH($dateValue = 1) { - return DateTimeExcel\Day::evaluate($dateValue); + return DateTimeExcel\DateParts::day($dateValue); } /** @@ -482,8 +482,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\WeekDay::evaluate() - * Use the evaluate method in the DateTimeExcel\WeekDay class instead + * @See DateTimeExcel\Week::day() + * Use the day method in the DateTimeExcel\Week class instead * * @param float|int|string $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string @@ -496,7 +496,7 @@ class DateTime */ public static function WEEKDAY($dateValue = 1, $style = 1) { - return DateTimeExcel\WeekDay::evaluate($dateValue, $style); + return DateTimeExcel\Week::day($dateValue, $style); } /** @@ -687,8 +687,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\WeekNum::evaluate() - * Use the evaluate method in the DateTimeExcel\WeekNum class instead + * @See DateTimeExcel\Week::number(() + * Use the number method in the DateTimeExcel\Week class instead * * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string @@ -708,7 +708,7 @@ class DateTime */ public static function WEEKNUM($dateValue = 1, $method = self::STARTWEEK_SUNDAY) { - return DateTimeExcel\WeekNum::evaluate($dateValue, $method); + return DateTimeExcel\Week::number($dateValue, $method); } /** @@ -721,8 +721,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\IsoWeekNum::evaluate() - * Use the evaluate method in the DateTimeExcel\IsoWeekNum class instead + * @See DateTimeExcel\Week::isoWeekNumber() + * Use the isoWeekNumber method in the DateTimeExcel\Week class instead * * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string @@ -731,7 +731,7 @@ class DateTime */ public static function ISOWEEKNUM($dateValue = 1) { - return DateTimeExcel\IsoWeekNum::evaluate($dateValue); + return DateTimeExcel\Week::isoWeekNumber($dateValue); } /** @@ -745,8 +745,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Month::evaluate() - * Use the evaluate method in the DateTimeExcel\Month class instead + * @See DateTimeExcel\DateParts::month() + * Use the month method in the DateTimeExcel\DateParts class instead * * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string @@ -755,7 +755,7 @@ class DateTime */ public static function MONTHOFYEAR($dateValue = 1) { - return DateTimeExcel\Month::evaluate($dateValue); + return DateTimeExcel\DateParts::month($dateValue); } /** @@ -769,8 +769,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Year::evaluate() - * Use the evaluate method in the DateTimeExcel\Year class instead + * @See DateTimeExcel\DateParts::year() + * Use the ear method in the DateTimeExcel\DateParts class instead * * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard date string @@ -779,7 +779,7 @@ class DateTime */ public static function YEAR($dateValue = 1) { - return DateTimeExcel\Year::evaluate($dateValue); + return DateTimeExcel\DateParts::year($dateValue); } /** @@ -793,8 +793,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Hour::evaluate() - * Use the evaluate method in the DateTimeExcel\Hour class instead + * @See DateTimeExcel\TimeParts::hour() + * Use the hour method in the DateTimeExcel\TimeParts class instead * * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard time string @@ -803,7 +803,7 @@ class DateTime */ public static function HOUROFDAY($timeValue = 0) { - return DateTimeExcel\Hour::evaluate($timeValue); + return DateTimeExcel\TimeParts::hour($timeValue); } /** @@ -817,8 +817,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Minute::evaluate() - * Use the evaluate method in the DateTimeExcel\Minute class instead + * @See DateTimeExcel\TimeParts::minute() + * Use the minute method in the DateTimeExcel\TimeParts class instead * * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard time string @@ -827,7 +827,7 @@ class DateTime */ public static function MINUTE($timeValue = 0) { - return DateTimeExcel\Minute::evaluate($timeValue); + return DateTimeExcel\TimeParts::minute($timeValue); } /** @@ -841,8 +841,8 @@ class DateTime * * @Deprecated 1.18.0 * - * @See DateTimeExcel\Second::evaluate() - * Use the evaluate method in the DateTimeExcel\Second class instead + * @See DateTimeExcel\TimeParts::second() + * Use the second method in the DateTimeExcel\TimeParts class instead * * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), * PHP DateTime object, or a standard time string @@ -851,7 +851,7 @@ class DateTime */ public static function SECOND($timeValue = 0) { - return DateTimeExcel\Second::evaluate($timeValue); + return DateTimeExcel\TimeParts::second($timeValue); } /** diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Now.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Current.php similarity index 51% rename from src/PhpSpreadsheet/Calculation/DateTimeExcel/Now.php rename to src/PhpSpreadsheet/Calculation/DateTimeExcel/Current.php index a0dea86f..7a70978e 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Now.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Current.php @@ -5,8 +5,33 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel; use DateTimeImmutable; use PhpOffice\PhpSpreadsheet\Calculation\Functions; -class Now +class Current { + /** + * DATENOW. + * + * Returns the current date. + * The NOW function is useful when you need to display the current date and time on a worksheet or + * calculate a value based on the current date and time, and have that value updated each time you + * open the worksheet. + * + * NOTE: When used in a Cell Formula, MS Excel changes the cell format so that it matches the date + * and time format of your regional settings. PhpSpreadsheet does not change cell formatting in this way. + * + * Excel Function: + * TODAY() + * + * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, + * depending on the value of the ReturnDateType flag + */ + public static function today() + { + $dti = new DateTimeImmutable(); + $dateArray = date_parse($dti->format('c')); + + return is_array($dateArray) ? Helpers::returnIn3FormatsArray($dateArray, true) : Functions::VALUE(); + } + /** * DATETIMENOW. * @@ -24,7 +49,7 @@ class Now * @return mixed Excel date/time serial value, PHP date/time serial value or PHP date/time object, * depending on the value of the ReturnDateType flag */ - public static function evaluate() + public static function now() { $dti = new DateTimeImmutable(); $dateArray = date_parse($dti->format('c')); diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateParts.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateParts.php new file mode 100644 index 00000000..f1ada435 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/DateParts.php @@ -0,0 +1,127 @@ += 0) { + return $weirdResult; + } + + try { + $dateValue = Helpers::getDateValue($dateValue); + } catch (Exception $e) { + return $e->getMessage(); + } + + // Execute function + $PHPDateObject = Date::excelToDateTimeObject($dateValue); + + return (int) $PHPDateObject->format('j'); + } + + /** + * MONTHOFYEAR. + * + * Returns the month of a date represented by a serial number. + * The month is given as an integer, ranging from 1 (January) to 12 (December). + * + * Excel Function: + * MONTH(dateValue) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * + * @return int|string Month of the year + */ + public static function month($dateValue) + { + try { + $dateValue = Helpers::getDateValue($dateValue); + } catch (Exception $e) { + return $e->getMessage(); + } + if ($dateValue < 1 && Date::getExcelCalendar() === DATE::CALENDAR_WINDOWS_1900) { + return 1; + } + + // Execute function + $PHPDateObject = Date::excelToDateTimeObject($dateValue); + + return (int) $PHPDateObject->format('n'); + } + + /** + * YEAR. + * + * Returns the year corresponding to a date. + * The year is returned as an integer in the range 1900-9999. + * + * Excel Function: + * YEAR(dateValue) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * + * @return int|string Year + */ + public static function year($dateValue) + { + try { + $dateValue = Helpers::getDateValue($dateValue); + } catch (Exception $e) { + return $e->getMessage(); + } + + if ($dateValue < 1 && Date::getExcelCalendar() === DATE::CALENDAR_WINDOWS_1900) { + return 1900; + } + // Execute function + $PHPDateObject = Date::excelToDateTimeObject($dateValue); + + return (int) $PHPDateObject->format('Y'); + } + + /** + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + */ + private static function weirdCondition($dateValue): int + { + // Excel does not treat 0 consistently for DAY vs. (MONTH or YEAR) + if (Date::getExcelCalendar() === DATE::CALENDAR_WINDOWS_1900 && Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) { + if (is_bool($dateValue)) { + return (int) $dateValue; + } + if ($dateValue === null) { + return 0; + } + if (is_numeric($dateValue) && $dateValue < 1 && $dateValue >= 0) { + return 0; + } + } + + return -1; + } +} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Day.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Day.php deleted file mode 100644 index bc57644d..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Day.php +++ /dev/null @@ -1,65 +0,0 @@ -= 0) { - return $weirdResult; - } - - try { - $dateValue = Helpers::getDateValue($dateValue); - } catch (Exception $e) { - return $e->getMessage(); - } - - // Execute function - $PHPDateObject = Date::excelToDateTimeObject($dateValue); - - return (int) $PHPDateObject->format('j'); - } - - /** - * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), - * PHP DateTime object, or a standard date string - */ - private static function weirdCondition($dateValue): int - { - // Excel does not treat 0 consistently for DAY vs. (MONTH or YEAR) - if (Date::getExcelCalendar() === DATE::CALENDAR_WINDOWS_1900 && Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) { - if (is_bool($dateValue)) { - return (int) $dateValue; - } - if ($dateValue === null) { - return 0; - } - if (is_numeric($dateValue) && $dateValue < 1 && $dateValue >= 0) { - return 0; - } - } - - return -1; - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Hour.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Hour.php deleted file mode 100644 index 84869036..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Hour.php +++ /dev/null @@ -1,44 +0,0 @@ -getMessage(); - } - - // Execute function - $timeValue = fmod($timeValue, 1); - $timeValue = Date::excelToDateTimeObject($timeValue); - - return (int) $timeValue->format('H'); - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/IsoWeekNum.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/IsoWeekNum.php deleted file mode 100644 index 7d2d65dc..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/IsoWeekNum.php +++ /dev/null @@ -1,59 +0,0 @@ -getMessage(); - } - - // Execute function - $PHPDateObject = Date::excelToDateTimeObject($dateValue); - Helpers::silly1900($PHPDateObject); - - return (int) $PHPDateObject->format('W'); - } - - /** - * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), - * PHP DateTime object, or a standard date string - */ - private static function apparentBug($dateValue): bool - { - if (Date::getExcelCalendar() !== DATE::CALENDAR_MAC_1904) { - if (is_bool($dateValue)) { - return true; - } - if (is_numeric($dateValue) && !((int) $dateValue)) { - return true; - } - } - - return false; - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Minute.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Minute.php deleted file mode 100644 index 1a9d5c21..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Minute.php +++ /dev/null @@ -1,44 +0,0 @@ -getMessage(); - } - - // Execute function - $timeValue = fmod($timeValue, 1); - $timeValue = Date::excelToDateTimeObject($timeValue); - - return (int) $timeValue->format('i'); - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php deleted file mode 100644 index 092370ba..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Month.php +++ /dev/null @@ -1,40 +0,0 @@ -getMessage(); - } - if ($dateValue < 1 && Date::getExcelCalendar() === DATE::CALENDAR_WINDOWS_1900) { - return 1; - } - - // Execute function - $PHPDateObject = Date::excelToDateTimeObject($dateValue); - - return (int) $PHPDateObject->format('n'); - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php index 5c586913..af6eda5c 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/NetworkDays.php @@ -56,7 +56,7 @@ class NetworkDays $holidayCountedArray = []; foreach ($holidayArray as $holidayDate) { if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) { - if ((WeekDay::evaluate($holidayDate, 2) < 6) && (!in_array($holidayDate, $holidayCountedArray))) { + if ((Week::day($holidayDate, 2) < 6) && (!in_array($holidayDate, $holidayCountedArray))) { --$partWeekDays; $holidayCountedArray[] = $holidayDate; } @@ -68,7 +68,7 @@ class NetworkDays private static function calcStartDow(float $startDate): int { - $startDow = 6 - (int) WeekDay::evaluate($startDate, 2); + $startDow = 6 - (int) Week::day($startDate, 2); if ($startDow < 0) { $startDow = 5; } @@ -78,7 +78,7 @@ class NetworkDays private static function calcEndDow(float $endDate): int { - $endDow = (int) WeekDay::evaluate($endDate, 2); + $endDow = (int) Week::day($endDate, 2); if ($endDow >= 6) { $endDow = 0; } diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Second.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Second.php deleted file mode 100644 index c3e15d86..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Second.php +++ /dev/null @@ -1,44 +0,0 @@ -getMessage(); - } - - // Execute function - $timeValue = fmod($timeValue, 1); - $timeValue = Date::excelToDateTimeObject($timeValue); - - return (int) $timeValue->format('s'); - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeParts.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeParts.php new file mode 100644 index 00000000..3e07da08 --- /dev/null +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/TimeParts.php @@ -0,0 +1,112 @@ +getMessage(); + } + + // Execute function + $timeValue = fmod($timeValue, 1); + $timeValue = Date::excelToDateTimeObject($timeValue); + + return (int) $timeValue->format('H'); + } + + /** + * MINUTE. + * + * Returns the minutes of a time value. + * The minute is given as an integer, ranging from 0 to 59. + * + * Excel Function: + * MINUTE(timeValue) + * + * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard time string + * + * @return int|string Minute + */ + public static function minute($timeValue) + { + try { + $timeValue = Functions::flattenSingleValue($timeValue); + Helpers::nullFalseTrueToNumber($timeValue); + if (!is_numeric($timeValue)) { + $timeValue = Helpers::getTimeValue($timeValue); + } + Helpers::validateNotNegative($timeValue); + } catch (Exception $e) { + return $e->getMessage(); + } + + // Execute function + $timeValue = fmod($timeValue, 1); + $timeValue = Date::excelToDateTimeObject($timeValue); + + return (int) $timeValue->format('i'); + } + + /** + * SECOND. + * + * Returns the seconds of a time value. + * The minute is given as an integer, ranging from 0 to 59. + * + * Excel Function: + * SECOND(timeValue) + * + * @param mixed $timeValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard time string + * + * @return int|string Second + */ + public static function second($timeValue) + { + try { + $timeValue = Functions::flattenSingleValue($timeValue); + Helpers::nullFalseTrueToNumber($timeValue); + if (!is_numeric($timeValue)) { + $timeValue = Helpers::getTimeValue($timeValue); + } + Helpers::validateNotNegative($timeValue); + } catch (Exception $e) { + return $e->getMessage(); + } + + // Execute function + $timeValue = fmod($timeValue, 1); + $timeValue = Date::excelToDateTimeObject($timeValue); + + return (int) $timeValue->format('s'); + } +} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Today.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Today.php deleted file mode 100644 index 545f0efb..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Today.php +++ /dev/null @@ -1,34 +0,0 @@ -format('c')); - - return is_array($dateArray) ? Helpers::returnIn3FormatsArray($dateArray, true) : Functions::VALUE(); - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WeekNum.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Week.php similarity index 55% rename from src/PhpSpreadsheet/Calculation/DateTimeExcel/WeekNum.php rename to src/PhpSpreadsheet/Calculation/DateTimeExcel/Week.php index 35634e4e..928bfc14 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WeekNum.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Week.php @@ -3,11 +3,11 @@ namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel; use DateTime; -use Exception; +use PhpOffice\PhpSpreadsheet\Calculation\Exception; use PhpOffice\PhpSpreadsheet\Calculation\Functions; use PhpOffice\PhpSpreadsheet\Shared\Date; -class WeekNum +class Week { /** * WEEKNUM. @@ -38,7 +38,7 @@ class WeekNum * * @return int|string Week Number */ - public static function evaluate($dateValue, $method = Constants::STARTWEEK_SUNDAY) + public static function number($dateValue, $method = Constants::STARTWEEK_SUNDAY) { $origDateValueNull = empty($dateValue); @@ -78,6 +78,129 @@ class WeekNum return (int) $weekOfYear; } + /** + * ISOWEEKNUM. + * + * Returns the ISO 8601 week number of the year for a specified date. + * + * Excel Function: + * ISOWEEKNUM(dateValue) + * + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * + * @return int|string Week Number + */ + public static function isoWeekNumber($dateValue) + { + if (self::apparentBug($dateValue)) { + return 52; + } + + try { + $dateValue = Helpers::getDateValue($dateValue); + } catch (Exception $e) { + return $e->getMessage(); + } + + // Execute function + $PHPDateObject = Date::excelToDateTimeObject($dateValue); + Helpers::silly1900($PHPDateObject); + + return (int) $PHPDateObject->format('W'); + } + + /** + * WEEKDAY. + * + * Returns the day of the week for a specified date. The day is given as an integer + * ranging from 0 to 7 (dependent on the requested style). + * + * Excel Function: + * WEEKDAY(dateValue[,style]) + * + * @param null|float|int|string $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + * @param mixed $style A number that determines the type of return value + * 1 or omitted Numbers 1 (Sunday) through 7 (Saturday). + * 2 Numbers 1 (Monday) through 7 (Sunday). + * 3 Numbers 0 (Monday) through 6 (Sunday). + * + * @return int|string Day of the week value + */ + public static function day($dateValue, $style = 1) + { + try { + $dateValue = Helpers::getDateValue($dateValue); + $style = self::validateStyle($style); + } catch (Exception $e) { + return $e->getMessage(); + } + + // Execute function + $PHPDateObject = Date::excelToDateTimeObject($dateValue); + Helpers::silly1900($PHPDateObject); + $DoW = (int) $PHPDateObject->format('w'); + + switch ($style) { + case 1: + ++$DoW; + + break; + case 2: + $DoW = self::dow0Becomes7($DoW); + + break; + case 3: + $DoW = self::dow0Becomes7($DoW) - 1; + + break; + } + + return $DoW; + } + + /** + * @param mixed $style expect int + */ + private static function validateStyle($style): int + { + $style = Functions::flattenSingleValue($style); + + if (!is_numeric($style)) { + throw new Exception(Functions::VALUE()); + } + $style = (int) $style; + if (($style < 1) || ($style > 3)) { + throw new Exception(Functions::NAN()); + } + + return $style; + } + + private static function dow0Becomes7(int $DoW): int + { + return ($DoW === 0) ? 7 : $DoW; + } + + /** + * @param mixed $dateValue Excel date serial value (float), PHP date timestamp (integer), + * PHP DateTime object, or a standard date string + */ + private static function apparentBug($dateValue): bool + { + if (Date::getExcelCalendar() !== DATE::CALENDAR_MAC_1904) { + if (is_bool($dateValue)) { + return true; + } + if (is_numeric($dateValue) && !((int) $dateValue)) { + return true; + } + } + + return false; + } + /** * Validate dateValue parameter. * @@ -125,6 +248,7 @@ class WeekNum { // This appears to be another Excel bug. - return $method === Constants::DOW_SUNDAY && Date::getExcelCalendar() === Date::CALENDAR_MAC_1904 && !$origNull && $dateObject->format('Y-m-d') === '1904-01-01'; + return $method === Constants::DOW_SUNDAY && Date::getExcelCalendar() === Date::CALENDAR_MAC_1904 && + !$origNull && $dateObject->format('Y-m-d') === '1904-01-01'; } } diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WeekDay.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/WeekDay.php deleted file mode 100644 index 6745557d..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WeekDay.php +++ /dev/null @@ -1,83 +0,0 @@ -getMessage(); - } - - // Execute function - $PHPDateObject = Date::excelToDateTimeObject($dateValue); - Helpers::silly1900($PHPDateObject); - $DoW = (int) $PHPDateObject->format('w'); - - switch ($style) { - case 1: - ++$DoW; - - break; - case 2: - $DoW = self::dow0Becomes7($DoW); - - break; - case 3: - $DoW = self::dow0Becomes7($DoW) - 1; - - break; - } - - return $DoW; - } - - /** - * @param mixed $style expect int - */ - private static function validateStyle($style): int - { - $style = Functions::flattenSingleValue($style); - - if (!is_numeric($style)) { - throw new Exception(Functions::VALUE()); - } - $style = (int) $style; - if (($style < 1) || ($style > 3)) { - throw new Exception(Functions::NAN()); - } - - return $style; - } - - private static function dow0Becomes7(int $DoW): int - { - return ($DoW === 0) ? 7 : $DoW; - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php index 502cc0d6..da7a81c5 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/WorkDay.php @@ -183,7 +183,7 @@ class WorkDay private static function getWeekDay(float $date, int $wd): int { - $result = WeekDay::evaluate($date, $wd); + $result = Week::day($date, $wd); return is_string($result) ? -1 : $result; } diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Year.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/Year.php deleted file mode 100644 index 2b7a10c6..00000000 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/Year.php +++ /dev/null @@ -1,40 +0,0 @@ -getMessage(); - } - - if ($dateValue < 1 && Date::getExcelCalendar() === DATE::CALENDAR_WINDOWS_1900) { - return 1900; - } - // Execute function - $PHPDateObject = Date::excelToDateTimeObject($dateValue); - - return (int) $PHPDateObject->format('Y'); - } -} diff --git a/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php b/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php index 3d49be47..ad300818 100644 --- a/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php +++ b/src/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php @@ -74,7 +74,7 @@ class YearFrac { if (Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_OPENOFFICE && Date::getExcelCalendar() !== Date::CALENDAR_MAC_1904) { if ($endDate === null && $startDate !== null) { - if (Month::evaluate($sDate) == 12 && Day::evaluate($sDate) === 31 && $method === 0) { + if (DateParts::month($sDate) == 12 && DateParts::day($sDate) === 31 && $method === 0) { $sDate += 2; } else { ++$sDate; @@ -88,13 +88,13 @@ class YearFrac private static function method1(float $startDate, float $endDate): float { $days = DateDif::evaluate($startDate, $endDate); - $startYear = (int) Year::evaluate($startDate); - $endYear = (int) Year::evaluate($endDate); + $startYear = (int) DateParts::year($startDate); + $endYear = (int) DateParts::year($endDate); $years = $endYear - $startYear + 1; - $startMonth = (int) Month::evaluate($startDate); - $startDay = (int) Day::evaluate($startDate); - $endMonth = (int) Month::evaluate($endDate); - $endDay = (int) Day::evaluate($endDate); + $startMonth = (int) DateParts::month($startDate); + $startDay = (int) DateParts::day($startDate); + $endMonth = (int) DateParts::month($endDate); + $endDay = (int) DateParts::day($endDate); $startMonthDay = 100 * $startMonth + $startDay; $endMonthDay = 100 * $endMonth + $endDay; if ($years == 1) { diff --git a/src/PhpSpreadsheet/Calculation/Financial/Amortization.php b/src/PhpSpreadsheet/Calculation/Financial/Amortization.php index c10e3304..048684d5 100644 --- a/src/PhpSpreadsheet/Calculation/Financial/Amortization.php +++ b/src/PhpSpreadsheet/Calculation/Financial/Amortization.php @@ -160,7 +160,7 @@ class Amortization $fOneRate = $cost * $rate; $fCostDelta = $cost - $salvage; // Note, quirky variation for leap years on the YEARFRAC for this function - $purchasedYear = DateTimeExcel\Year::evaluate($purchased); + $purchasedYear = DateTimeExcel\DateParts::year($purchased); $yearFrac = DateTimeExcel\YearFrac::evaluate($purchased, $firstPeriod, $basis); if (is_string($yearFrac)) { return $yearFrac; diff --git a/src/PhpSpreadsheet/Calculation/Financial/Coupons.php b/src/PhpSpreadsheet/Calculation/Financial/Coupons.php index 7f8f4b7c..a39688d5 100644 --- a/src/PhpSpreadsheet/Calculation/Financial/Coupons.php +++ b/src/PhpSpreadsheet/Calculation/Financial/Coupons.php @@ -63,7 +63,7 @@ class Coupons return $e->getMessage(); } - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\Year::evaluate($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); if (is_string($daysPerYear)) { return Functions::VALUE(); } @@ -133,7 +133,7 @@ class Coupons case FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL: // Actual/actual if ($frequency == FinancialConstants::FREQUENCY_ANNUAL) { - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\Year::evaluate($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); return $daysPerYear / $frequency; } @@ -197,7 +197,7 @@ class Coupons return $e->getMessage(); } - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\Year::evaluate($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); $next = self::couponFirstPeriodDate($settlement, $maturity, $frequency, self::PERIOD_DATE_NEXT); if ($basis === FinancialConstants::BASIS_DAYS_PER_YEAR_NASD) { diff --git a/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php b/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php index 2c43254c..d1d0c8ff 100644 --- a/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php +++ b/src/PhpSpreadsheet/Calculation/Financial/Securities/Price.php @@ -194,7 +194,7 @@ class Price return $e->getMessage(); } - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\Year::evaluate($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); if (!is_numeric($daysPerYear)) { return $daysPerYear; } diff --git a/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php b/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php index 416a9c50..4a0d0873 100644 --- a/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php +++ b/src/PhpSpreadsheet/Calculation/Financial/Securities/Yields.php @@ -57,7 +57,7 @@ class Yields return $e->getMessage(); } - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\Year::evaluate($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); if (!is_numeric($daysPerYear)) { return $daysPerYear; } @@ -122,7 +122,7 @@ class Yields return $e->getMessage(); } - $daysPerYear = Helpers::daysPerYear(DateTimeExcel\Year::evaluate($settlement), $basis); + $daysPerYear = Helpers::daysPerYear(DateTimeExcel\DateParts::year($settlement), $basis); if (!is_numeric($daysPerYear)) { return $daysPerYear; } diff --git a/src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php b/src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php index 2e186d52..c60af0b0 100644 --- a/src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php +++ b/src/PhpSpreadsheet/Calculation/Financial/TreasuryBill.php @@ -43,7 +43,7 @@ class TreasuryBill $daysBetweenSettlementAndMaturity = $maturity - $settlement; $daysPerYear = Helpers::daysPerYear( - DateTimeExcel\Year::evaluate($maturity), + DateTimeExcel\DateParts::year($maturity), FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL ); @@ -88,7 +88,7 @@ class TreasuryBill $daysBetweenSettlementAndMaturity = $maturity - $settlement; $daysPerYear = Helpers::daysPerYear( - DateTimeExcel\Year::evaluate($maturity), + DateTimeExcel\DateParts::year($maturity), FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL ); @@ -134,7 +134,7 @@ class TreasuryBill $daysBetweenSettlementAndMaturity = $maturity - $settlement; $daysPerYear = Helpers::daysPerYear( - DateTimeExcel\Year::evaluate($maturity), + DateTimeExcel\DateParts::year($maturity), FinancialConstants::BASIS_DAYS_PER_YEAR_ACTUAL ); diff --git a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php index 30898988..625e4414 100644 --- a/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php +++ b/tests/PhpSpreadsheetTests/Calculation/Functions/DateTime/WeekDayTest.php @@ -2,7 +2,7 @@ namespace PhpOffice\PhpSpreadsheetTests\Calculation\Functions\DateTime; -use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\WeekDay; +use PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel\Week; class WeekDayTest extends AllSetupTeardown { @@ -28,8 +28,8 @@ class WeekDayTest extends AllSetupTeardown public function testWEEKDAYwith1904Calendar(): void { self::setMac1904(); - self::assertEquals(7, WeekDay::evaluate('1904-01-02')); - self::assertEquals(6, WeekDay::evaluate('1904-01-01')); - self::assertEquals(6, WeekDay::evaluate(null)); + self::assertEquals(7, Week::day('1904-01-02')); + self::assertEquals(6, Week::day('1904-01-01')); + self::assertEquals(6, Week::day(null)); } }