Differences Between: [Versions 400 and 401] [Versions 400 and 402] [Versions 400 and 403]
1 <?php 2 3 namespace PhpOffice\PhpSpreadsheet\Calculation\DateTimeExcel; 4 5 use DateTime; 6 use PhpOffice\PhpSpreadsheet\Calculation\Exception; 7 use PhpOffice\PhpSpreadsheet\Calculation\Functions; 8 use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDateHelper; 9 10 class Helpers 11 { 12 /** 13 * Identify if a year is a leap year or not. 14 * 15 * @param int|string $year The year to test 16 * 17 * @return bool TRUE if the year is a leap year, otherwise FALSE 18 */ 19 public static function isLeapYear($year): bool 20 { 21 return (($year % 4) === 0) && (($year % 100) !== 0) || (($year % 400) === 0); 22 } 23 24 /** 25 * getDateValue. 26 * 27 * @param mixed $dateValue 28 * 29 * @return float Excel date/time serial value 30 */ 31 public static function getDateValue($dateValue, bool $allowBool = true): float 32 { 33 if (is_object($dateValue)) { 34 $retval = SharedDateHelper::PHPToExcel($dateValue); 35 if (is_bool($retval)) { 36 throw new Exception(Functions::VALUE()); 37 } 38 39 return $retval; 40 } 41 42 self::nullFalseTrueToNumber($dateValue, $allowBool); 43 if (!is_numeric($dateValue)) { 44 $saveReturnDateType = Functions::getReturnDateType(); 45 Functions::setReturnDateType(Functions::RETURNDATE_EXCEL); 46 $dateValue = DateValue::fromString($dateValue); 47 Functions::setReturnDateType($saveReturnDateType); 48 if (!is_numeric($dateValue)) { 49 throw new Exception(Functions::VALUE()); 50 } 51 } 52 if ($dateValue < 0 && Functions::getCompatibilityMode() !== Functions::COMPATIBILITY_OPENOFFICE) { 53 throw new Exception(Functions::NAN()); 54 } 55 56 return (float) $dateValue; 57 } 58 59 /** 60 * getTimeValue. 61 * 62 * @param string $timeValue 63 * 64 * @return mixed Excel date/time serial value, or string if error 65 */ 66 public static function getTimeValue($timeValue) 67 { 68 $saveReturnDateType = Functions::getReturnDateType(); 69 Functions::setReturnDateType(Functions::RETURNDATE_EXCEL); 70 $timeValue = TimeValue::fromString($timeValue); 71 Functions::setReturnDateType($saveReturnDateType); 72 73 return $timeValue; 74 } 75 76 /** 77 * Adjust date by given months. 78 * 79 * @param mixed $dateValue 80 */ 81 public static function adjustDateByMonths($dateValue = 0, float $adjustmentMonths = 0): DateTime 82 { 83 // Execute function 84 $PHPDateObject = SharedDateHelper::excelToDateTimeObject($dateValue); 85 $oMonth = (int) $PHPDateObject->format('m'); 86 $oYear = (int) $PHPDateObject->format('Y'); 87 88 $adjustmentMonthsString = (string) $adjustmentMonths; 89 if ($adjustmentMonths > 0) { 90 $adjustmentMonthsString = '+' . $adjustmentMonths; 91 } 92 if ($adjustmentMonths != 0) { 93 $PHPDateObject->modify($adjustmentMonthsString . ' months'); 94 } 95 $nMonth = (int) $PHPDateObject->format('m'); 96 $nYear = (int) $PHPDateObject->format('Y'); 97 98 $monthDiff = ($nMonth - $oMonth) + (($nYear - $oYear) * 12); 99 if ($monthDiff != $adjustmentMonths) { 100 $adjustDays = (int) $PHPDateObject->format('d'); 101 $adjustDaysString = '-' . $adjustDays . ' days'; 102 $PHPDateObject->modify($adjustDaysString); 103 } 104 105 return $PHPDateObject; 106 } 107 108 /** 109 * Help reduce perceived complexity of some tests. 110 * 111 * @param mixed $value 112 * @param mixed $altValue 113 */ 114 public static function replaceIfEmpty(&$value, $altValue): void 115 { 116 $value = $value ?: $altValue; 117 } 118 119 /** 120 * Adjust year in ambiguous situations. 121 */ 122 public static function adjustYear(string $testVal1, string $testVal2, string &$testVal3): void 123 { 124 if (!is_numeric($testVal1) || $testVal1 < 31) { 125 if (!is_numeric($testVal2) || $testVal2 < 12) { 126 if (is_numeric($testVal3) && $testVal3 < 12) { 127 $testVal3 += 2000; 128 } 129 } 130 } 131 } 132 133 /** 134 * Return result in one of three formats. 135 * 136 * @return mixed 137 */ 138 public static function returnIn3FormatsArray(array $dateArray, bool $noFrac = false) 139 { 140 $retType = Functions::getReturnDateType(); 141 if ($retType === Functions::RETURNDATE_PHP_DATETIME_OBJECT) { 142 return new DateTime( 143 $dateArray['year'] 144 . '-' . $dateArray['month'] 145 . '-' . $dateArray['day'] 146 . ' ' . $dateArray['hour'] 147 . ':' . $dateArray['minute'] 148 . ':' . $dateArray['second'] 149 ); 150 } 151 $excelDateValue = 152 SharedDateHelper::formattedPHPToExcel( 153 $dateArray['year'], 154 $dateArray['month'], 155 $dateArray['day'], 156 $dateArray['hour'], 157 $dateArray['minute'], 158 $dateArray['second'] 159 ); 160 if ($retType === Functions::RETURNDATE_EXCEL) { 161 return $noFrac ? floor($excelDateValue) : (float) $excelDateValue; 162 } 163 // RETURNDATE_UNIX_TIMESTAMP) 164 165 return (int) SharedDateHelper::excelToTimestamp($excelDateValue); 166 } 167 168 /** 169 * Return result in one of three formats. 170 * 171 * @return mixed 172 */ 173 public static function returnIn3FormatsFloat(float $excelDateValue) 174 { 175 $retType = Functions::getReturnDateType(); 176 if ($retType === Functions::RETURNDATE_EXCEL) { 177 return $excelDateValue; 178 } 179 if ($retType === Functions::RETURNDATE_UNIX_TIMESTAMP) { 180 return (int) SharedDateHelper::excelToTimestamp($excelDateValue); 181 } 182 // RETURNDATE_PHP_DATETIME_OBJECT 183 184 return SharedDateHelper::excelToDateTimeObject($excelDateValue); 185 } 186 187 /** 188 * Return result in one of three formats. 189 * 190 * @return mixed 191 */ 192 public static function returnIn3FormatsObject(DateTime $PHPDateObject) 193 { 194 $retType = Functions::getReturnDateType(); 195 if ($retType === Functions::RETURNDATE_PHP_DATETIME_OBJECT) { 196 return $PHPDateObject; 197 } 198 if ($retType === Functions::RETURNDATE_EXCEL) { 199 return (float) SharedDateHelper::PHPToExcel($PHPDateObject); 200 } 201 // RETURNDATE_UNIX_TIMESTAMP 202 $stamp = SharedDateHelper::PHPToExcel($PHPDateObject); 203 $stamp = is_bool($stamp) ? ((int) $stamp) : $stamp; 204 205 return (int) SharedDateHelper::excelToTimestamp($stamp); 206 } 207 208 private static function baseDate(): int 209 { 210 if (Functions::getCompatibilityMode() === Functions::COMPATIBILITY_OPENOFFICE) { 211 return 0; 212 } 213 if (SharedDateHelper::getExcelCalendar() === SharedDateHelper::CALENDAR_MAC_1904) { 214 return 0; 215 } 216 217 return 1; 218 } 219 220 /** 221 * Many functions accept null/false/true argument treated as 0/0/1. 222 * 223 * @param mixed $number 224 */ 225 public static function nullFalseTrueToNumber(&$number, bool $allowBool = true): void 226 { 227 $number = Functions::flattenSingleValue($number); 228 $nullVal = self::baseDate(); 229 if ($number === null) { 230 $number = $nullVal; 231 } elseif ($allowBool && is_bool($number)) { 232 $number = $nullVal + (int) $number; 233 } 234 } 235 236 /** 237 * Many functions accept null argument treated as 0. 238 * 239 * @param mixed $number 240 * 241 * @return float|int 242 */ 243 public static function validateNumericNull($number) 244 { 245 $number = Functions::flattenSingleValue($number); 246 if ($number === null) { 247 return 0; 248 } 249 if (is_int($number)) { 250 return $number; 251 } 252 if (is_numeric($number)) { 253 return (float) $number; 254 } 255 256 throw new Exception(Functions::VALUE()); 257 } 258 259 /** 260 * Many functions accept null/false/true argument treated as 0/0/1. 261 * 262 * @param mixed $number 263 * 264 * @return float 265 */ 266 public static function validateNotNegative($number) 267 { 268 if (!is_numeric($number)) { 269 throw new Exception(Functions::VALUE()); 270 } 271 if ($number >= 0) { 272 return (float) $number; 273 } 274 275 throw new Exception(Functions::NAN()); 276 } 277 278 public static function silly1900(DateTime $PHPDateObject, string $mod = '-1 day'): void 279 { 280 $isoDate = $PHPDateObject->format('c'); 281 if ($isoDate < '1900-03-01') { 282 $PHPDateObject->modify($mod); 283 } 284 } 285 286 public static function dateParse(string $string): array 287 { 288 return self::forceArray(date_parse($string)); 289 } 290 291 public static function dateParseSucceeded(array $dateArray): bool 292 { 293 return $dateArray['error_count'] === 0; 294 } 295 296 /** 297 * Despite documentation, date_parse probably never returns false. 298 * Just in case, this routine helps guarantee it. 299 * 300 * @param array|false $dateArray 301 */ 302 private static function forceArray($dateArray): array 303 { 304 return is_array($dateArray) ? $dateArray : ['error_count' => 1]; 305 } 306 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body