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)); } }