PluginProbe
TablePress – Tables in WordPress made easy / 3.4
TablePress – Tables in WordPress made easy v3.4
3.4 3.3.4 3.3.3 3.3.2 3.3.1 trunk 1.12 1.14 1.9.2 2.0.4 2.1.7 2.1.8 2.2 2.2.1 2.2.2 2.2.3 2.2.4 2.2.5 2.3 2.3.1 2.3.2 2.4 2.4.1 2.4.2 2.4.3 All 45 releases
tablepress / libraries / vendor / PhpSpreadsheet / Calculation / DateTimeExcel / YearFrac.php

YearFrac.php in TablePress – Tables in WordPress made easy 3.4, at libraries/vendor/PhpSpreadsheet/Calculation/DateTimeExcel/YearFrac.php

133 lines 5.2 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 <?php
2
3 namespace TablePress\PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel;
4
5 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
6 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Exception;
7 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Functions;
8 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Information\ExcelError;
9 use TablePress\PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper;
10
11 class YearFrac
12 {
13 use ArrayEnabled;
14
15 /**
16 * YEARFRAC.
17 *
18 * Calculates the fraction of the year represented by the number of whole days between two dates
19 * (the start_date and the end_date).
20 * Use the YEARFRAC worksheet function to identify the proportion of a whole year's benefits or
21 * obligations to assign to a specific term.
22 *
23 * Excel Function:
24 * YEARFRAC(startDate,endDate[,method])
25 * See https://lists.oasis-open.org/archives/office-formula/200806/msg00039.html
26 * for description of algorithm used in Excel
27 *
28 * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer),
29 * PHP DateTime object, or a standard date string
30 * Or can be an array of values
31 * @param mixed $endDate Excel date serial value (float), PHP date timestamp (integer),
32 * PHP DateTime object, or a standard date string
33 * Or can be an array of methods
34 * @param array<mixed>|int $method Method used for the calculation
35 * 0 or omitted US (NASD) 30/360
36 * 1 Actual/actual
37 * 2 Actual/360
38 * 3 Actual/365
39 * 4 European 30/360
40 * Or can be an array of methods
41 *
42 * @return array<mixed>|float|int|string fraction of the year, or a string containing an error
43 * If an array of values is passed for the $startDate or $endDays,arguments, then the returned result
44 * will also be an array with matching dimensions
45 */
46 public static function fraction($startDate, $endDate, $method = 0)
47 {
48 if (is_array($startDate) || is_array($endDate) || is_array($method)) {
49 return self::evaluateArrayArguments([self::class, __FUNCTION__], $startDate, $endDate, $method);
50 }
51
52 try {
53 $method = (int) Helpers::validateNumericNull($method);
54 $sDate = Helpers::getDateValue($startDate);
55 $eDate = Helpers::getDateValue($endDate);
56 $sDate = self::excelBug($sDate, $startDate, $endDate, $method);
57 $eDate = self::excelBug($eDate, $endDate, $startDate, $method);
58 $startDate = min($sDate, $eDate);
59 $endDate = max($sDate, $eDate);
60 } catch (Exception $e) {
61 return $e->getMessage();
62 }
63
64 switch ($method) {
65 case 0:
66 return Helpers::floatOrInt(Days360::between($startDate, $endDate)) / 360;
67 case 1:
68 return self::method1($startDate, $endDate);
69 case 2:
70 return Helpers::floatOrInt(Difference::interval($startDate, $endDate)) / 360;
71 case 3:
72 return Helpers::floatOrInt(Difference::interval($startDate, $endDate)) / 365;
73 case 4:
74 return Helpers::floatOrInt(Days360::between($startDate, $endDate, true)) / 360;
75 default:
76 return ExcelError::NAN();
77 }
78 }
79
80 /**
81 * Excel 1900 calendar treats date argument of null as 1900-01-00. Really.
82 * @param mixed $startDate
83 * @param mixed $endDate
84 */
85 private static function excelBug(float $sDate, $startDate, $endDate, int $method): float
86 {
87 if (Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_OPENOFFICE && SharedDateHelper::getExcelCalendar() !== SharedDateHelper::CALENDAR_MAC_1904) {
88 if ($endDate === null && $startDate !== null) {
89 if (DateParts::month($sDate) == 12 && DateParts::day($sDate) === 31 && $method === 0) {
90 $sDate += 2;
91 } else {
92 ++$sDate;
93 }
94 }
95 }
96
97 return $sDate;
98 }
99
100 private static function method1(float $startDate, float $endDate): float
101 {
102 $days = Helpers::floatOrInt(Difference::interval($startDate, $endDate));
103 $startYear = (int) DateParts::year($startDate);
104 $endYear = (int) DateParts::year($endDate);
105 $years = $endYear - $startYear + 1;
106 $startMonth = (int) DateParts::month($startDate);
107 $startDay = (int) DateParts::day($startDate);
108 $endMonth = (int) DateParts::month($endDate);
109 $endDay = (int) DateParts::day($endDate);
110 $startMonthDay = 100 * $startMonth + $startDay;
111 $endMonthDay = 100 * $endMonth + $endDay;
112 if ($years == 1) {
113 $tmpCalcAnnualBasis = 365 + (int) Helpers::isLeapYear($endYear);
114 } elseif ($years == 2 && $startMonthDay >= $endMonthDay) {
115 if (Helpers::isLeapYear($startYear)) {
116 $tmpCalcAnnualBasis = 365 + (int) ($startMonthDay <= 229);
117 } elseif (Helpers::isLeapYear($endYear)) {
118 $tmpCalcAnnualBasis = 365 + (int) ($endMonthDay >= 229);
119 } else {
120 $tmpCalcAnnualBasis = 365;
121 }
122 } else {
123 $tmpCalcAnnualBasis = 0;
124 for ($year = $startYear; $year <= $endYear; ++$year) {
125 $tmpCalcAnnualBasis += 365 + (int) Helpers::isLeapYear($year);
126 }
127 $tmpCalcAnnualBasis /= $years;
128 }
129
130 return $days / $tmpCalcAnnualBasis;
131 }
132 }
133