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 / WorkDay.php

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

209 lines 6.6 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 DateTime;
6 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\ArrayEnabled;
7 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Exception;
8 use TablePress\PhpOffice\PhpSpreadsheet\Calculation\Functions;
9
10 class WorkDay
11 {
12 use ArrayEnabled;
13
14 /**
15 * WORKDAY.
16 *
17 * Returns the date that is the indicated number of working days before or after a date (the
18 * starting date). Working days exclude weekends and any dates identified as holidays.
19 * Use WORKDAY to exclude weekends or holidays when you calculate invoice due dates, expected
20 * delivery times, or the number of days of work performed.
21 *
22 * Excel Function:
23 * WORKDAY(startDate,endDays[,holidays[,holiday[,...]]])
24 *
25 * @param mixed $startDate Excel date serial value (float), PHP date timestamp (integer),
26 * PHP DateTime object, or a standard date string
27 * Or can be an array of date values
28 * @param array<mixed>|int $endDays The number of nonweekend and nonholiday days before or after
29 * startDate. A positive value for days yields a future date; a
30 * negative value yields a past date.
31 * Or can be an array of int values
32 * @param mixed $dateArgs An array of dates (such as holidays) to exclude from the calculation
33 *
34 * @return array<mixed>|DateTime|float|int|string Excel date/time serial value, PHP date/time serial value or PHP date/time object,
35 * depending on the value of the ReturnDateType flag
36 * If an array of values is passed for the $startDate or $endDays,arguments, then the returned result
37 * will also be an array with matching dimensions
38 */
39 public static function date($startDate, $endDays, ...$dateArgs)
40 {
41 if (is_array($startDate) || is_array($endDays)) {
42 return self::evaluateArrayArgumentsSubset(
43 [self::class, __FUNCTION__],
44 2,
45 $startDate,
46 $endDays,
47 ...$dateArgs
48 );
49 }
50
51 // Retrieve the mandatory start date and days that are referenced in the function definition
52 try {
53 $startDate = Helpers::getDateValue($startDate);
54 $endDays = Helpers::validateNumericNull($endDays);
55 $holidayArray = array_map([Helpers::class, 'getDateValue'], Functions::flattenArray($dateArgs));
56 } catch (Exception $e) {
57 return $e->getMessage();
58 }
59
60 $startDate = (float) floor($startDate);
61 $endDays = (int) floor($endDays);
62 // If endDays is 0, we always return startDate
63 if ($endDays == 0) {
64 return $startDate;
65 }
66 if ($endDays < 0) {
67 return self::decrementing($startDate, $endDays, $holidayArray);
68 }
69
70 return self::incrementing($startDate, $endDays, $holidayArray);
71 }
72
73 /**
74 * Use incrementing logic to determine Workday.
75 *
76 * @param array<mixed> $holidayArray
77 * @return float|int|\DateTime
78 */
79 private static function incrementing(float $startDate, int $endDays, array $holidayArray)
80 {
81 // Adjust the start date if it falls over a weekend
82 $startDoW = self::getWeekDay($startDate, 3);
83 if ($startDoW >= 5) {
84 $startDate += 7 - $startDoW;
85 --$endDays;
86 }
87
88 // Add endDays
89 $endDate = (float) $startDate + ((int) ($endDays / 5) * 7);
90 $endDays = $endDays % 5;
91 while ($endDays > 0) {
92 ++$endDate;
93 // Adjust the calculated end date if it falls over a weekend
94 $endDow = self::getWeekDay($endDate, 3);
95 if ($endDow >= 5) {
96 $endDate += 7 - $endDow;
97 }
98 --$endDays;
99 }
100
101 // Test any extra holiday parameters
102 if (!empty($holidayArray)) {
103 $endDate = self::incrementingArray($startDate, $endDate, $holidayArray);
104 }
105
106 return Helpers::returnIn3FormatsFloat($endDate);
107 }
108
109 /** @param array<mixed> $holidayArray */
110 private static function incrementingArray(float $startDate, float $endDate, array $holidayArray): float
111 {
112 $holidayCountedArray = $holidayDates = [];
113 foreach ($holidayArray as $holidayDate) {
114 /** @var float $holidayDate */
115 if (self::getWeekDay($holidayDate, 3) < 5) {
116 $holidayDates[] = $holidayDate;
117 }
118 }
119 sort($holidayDates, SORT_NUMERIC);
120 foreach ($holidayDates as $holidayDate) {
121 if (($holidayDate >= $startDate) && ($holidayDate <= $endDate)) {
122 if (!in_array($holidayDate, $holidayCountedArray)) {
123 ++$endDate;
124 $holidayCountedArray[] = $holidayDate;
125 }
126 }
127 // Adjust the calculated end date if it falls over a weekend
128 $endDoW = self::getWeekDay($endDate, 3);
129 if ($endDoW >= 5) {
130 $endDate += 7 - $endDoW;
131 }
132 }
133
134 return $endDate;
135 }
136
137 /**
138 * Use decrementing logic to determine Workday.
139 *
140 * @param array<mixed> $holidayArray
141 * @return float|int|\DateTime
142 */
143 private static function decrementing(float $startDate, int $endDays, array $holidayArray)
144 {
145 // Adjust the start date if it falls over a weekend
146 $startDoW = self::getWeekDay($startDate, 3);
147 if ($startDoW >= 5) {
148 $startDate += -$startDoW + 4;
149 ++$endDays;
150 }
151
152 // Add endDays
153 $endDate = (float) $startDate + ((int) ($endDays / 5) * 7);
154 $endDays = $endDays % 5;
155 while ($endDays < 0) {
156 --$endDate;
157 // Adjust the calculated end date if it falls over a weekend
158 $endDow = self::getWeekDay($endDate, 3);
159 if ($endDow >= 5) {
160 $endDate += 4 - $endDow;
161 }
162 ++$endDays;
163 }
164
165 // Test any extra holiday parameters
166 if (!empty($holidayArray)) {
167 $endDate = self::decrementingArray($startDate, $endDate, $holidayArray);
168 }
169
170 return Helpers::returnIn3FormatsFloat($endDate);
171 }
172
173 /** @param array<mixed> $holidayArray */
174 private static function decrementingArray(float $startDate, float $endDate, array $holidayArray): float
175 {
176 $holidayCountedArray = $holidayDates = [];
177 foreach ($holidayArray as $holidayDate) {
178 /** @var float $holidayDate */
179 if (self::getWeekDay($holidayDate, 3) < 5) {
180 $holidayDates[] = $holidayDate;
181 }
182 }
183 rsort($holidayDates, SORT_NUMERIC);
184 foreach ($holidayDates as $holidayDate) {
185 if (($holidayDate <= $startDate) && ($holidayDate >= $endDate)) {
186 if (!in_array($holidayDate, $holidayCountedArray)) {
187 --$endDate;
188 $holidayCountedArray[] = $holidayDate;
189 }
190 }
191 // Adjust the calculated end date if it falls over a weekend
192 $endDoW = self::getWeekDay($endDate, 3);
193 /** int $endDoW */
194 if ($endDoW >= 5) {
195 $endDate += -$endDoW + 4;
196 }
197 }
198
199 return $endDate;
200 }
201
202 private static function getWeekDay(float $date, int $wd): int
203 {
204 $result = Functions::scalar(Week::day($date, $wd));
205
206 return is_int($result) ? $result : -1;
207 }
208 }
209