| @@ -160,9 +160,9 @@ | ||
| 160 | 160 | * serialized timestamp. |
| 161 | 161 | * See https://en.wikipedia.org/wiki/ISO_8601 for details of the ISO-8601 standard format. |
| 162 | 162 | * @return float|int |
| 163 | 163 | */ |
| 164 | - public static function convertIsoDate($value) | |
| 164 | + public static function convertIsoDate($value, ?int $calendar = null) | |
| 165 | 165 | { |
| 166 | 166 | if (!is_string($value)) { |
| 167 | 167 | throw new Exception('Non-string value supplied for Iso Date conversion'); |
| 168 | 168 | } |
| @@ -173,9 +173,9 @@ | ||
| 173 | 173 | if (is_array($dateErrors) && ($dateErrors['warning_count'] > 0 || $dateErrors['error_count'] > 0)) { |
| 174 | 174 | throw new Exception("Invalid string $value supplied for datatype Date"); |
| 175 | 175 | } |
| 176 | 176 | |
| 177 | - $newValue = self::dateTimeToExcel($date); | |
| 177 | + $newValue = self::dateTimeToExcel($date, $calendar); | |
| 178 | 178 | |
| 179 | 179 | if (preg_match('/^\s*\d?\d:\d\d(:\d\d([.]\d+)?)?\s*(am|pm)?\s*$/i', $value) == 1) { |
| 180 | 180 | $newValue = fmod($newValue, 1.0); |
| 181 | 181 | } |
| @@ -194,18 +194,19 @@ | ||
| 194 | 194 | * @throws \Exception |
| 195 | 195 | * |
| 196 | 196 | * @return DateTime PHP date/time object |
| 197 | 197 | */ |
| 198 | - public static function excelToDateTimeObject($excelTimestamp, $timeZone = null): DateTime | |
| 198 | + public static function excelToDateTimeObject($excelTimestamp, $timeZone = null, ?int $calendar = null): DateTime | |
| 199 | 199 | { |
| 200 | + $calendar ??= self::$excelCalendar; | |
| 200 | 201 | $timeZone = ($timeZone === null) ? self::getDefaultTimezone() : self::validateTimeZone($timeZone); |
| 201 | 202 | if (Functions::getCompatibilityMode() == Functions::COMPATIBILITY_EXCEL) { |
| 202 | - if ($excelTimestamp < 1 && self::$excelCalendar === self::CALENDAR_WINDOWS_1900) { | |
| 203 | + if ($excelTimestamp < 1 && $calendar === self::CALENDAR_WINDOWS_1900) { | |
| 203 | 204 | // Unix timestamp base date |
| 204 | 205 | $baseDate = new DateTime('1970-01-01', $timeZone); |
| 205 | 206 | } else { |
| 206 | 207 | // MS Excel calendar base dates |
| 207 | - if (self::$excelCalendar == self::CALENDAR_WINDOWS_1900) { | |
| 208 | + if ($calendar == self::CALENDAR_WINDOWS_1900) { | |
| 208 | 209 | // Allow adjustment for 1900 Leap Year in MS Excel |
| 209 | 210 | $baseDate = ($excelTimestamp < 60) ? new DateTime('1899-12-31', $timeZone) : new DateTime('1899-12-30', $timeZone); |
| 210 | 211 | } else { |
| 211 | 212 | $baseDate = new DateTime('1904-01-01', $timeZone); |
| @@ -252,11 +253,11 @@ | ||
| 252 | 253 | * Use the default (UTC) unless you absolutely need a conversion |
| 253 | 254 | * |
| 254 | 255 | * @return int Unix timetamp for this date/time |
| 255 | 256 | */ |
| 256 | - public static function excelToTimestamp($excelTimestamp, $timeZone = null): int | |
| 257 | + public static function excelToTimestamp($excelTimestamp, $timeZone = null, ?int $calendar = null): int | |
| 257 | 258 | { |
| 258 | - $dto = self::excelToDateTimeObject($excelTimestamp, $timeZone); | |
| 259 | + $dto = self::excelToDateTimeObject($excelTimestamp, $timeZone, $calendar); | |
| 259 | 260 | self::roundMicroseconds($dto); |
| 260 | 261 | |
| 261 | 262 | return (int) $dto->format('U'); |
| 262 | 263 | } |
| @@ -269,17 +270,19 @@ | ||
| 269 | 270 | * |
| 270 | 271 | * @return false|float Excel date/time value |
| 271 | 272 | * or boolean FALSE on failure |
| 272 | 273 | */ |
| 273 | - public static function PHPToExcel($dateValue) | |
| 274 | + public static function PHPToExcel($dateValue, ?int $calendar = null) | |
| 274 | 275 | { |
| 275 | 276 | if ((is_object($dateValue)) && ($dateValue instanceof DateTimeInterface)) { |
| 276 | - return self::dateTimeToExcel($dateValue); | |
| 277 | - } elseif (is_numeric($dateValue)) { | |
| 278 | - return self::timestampToExcel($dateValue); | |
| 279 | - } elseif (is_string($dateValue)) { | |
| 280 | - return self::stringToExcel($dateValue); | |
| 277 | + return self::dateTimeToExcel($dateValue, $calendar); | |
| 281 | 278 | } |
| 279 | + if (is_numeric($dateValue)) { | |
| 280 | + return self::timestampToExcel($dateValue, $calendar); | |
| 281 | + } | |
| 282 | + if (is_string($dateValue)) { | |
| 283 | + return self::stringToExcel($dateValue, $calendar); | |
| 284 | + } | |
| 282 | 285 | |
| 283 | 286 | return false; |
| 284 | 287 | } |
| 285 | 288 | |
| @@ -289,9 +292,9 @@ | ||
| 289 | 292 | * @param DateTimeInterface $dateValue PHP DateTime object |
| 290 | 293 | * |
| 291 | 294 | * @return float MS Excel serialized date/time value |
| 292 | 295 | */ |
| 293 | - public static function dateTimeToExcel(DateTimeInterface $dateValue): float | |
| 296 | + public static function dateTimeToExcel(DateTimeInterface $dateValue, ?int $calendar = null): float | |
| 294 | 297 | { |
| 295 | 298 | $seconds = (float) sprintf('%d.%06d', $dateValue->format('s'), $dateValue->format('u')); |
| 296 | 299 | |
| 297 | 300 | return self::formattedPHPToExcel( |
| @@ -299,9 +302,10 @@ | ||
| 299 | 302 | (int) $dateValue->format('m'), |
| 300 | 303 | (int) $dateValue->format('d'), |
| 301 | 304 | (int) $dateValue->format('H'), |
| 302 | 305 | (int) $dateValue->format('i'), |
| 303 | - $seconds | |
| 306 | + $seconds, | |
| 307 | + $calendar | |
| 304 | 308 | ); |
| 305 | 309 | } |
| 306 | 310 | |
| 307 | 311 | /** |
| @@ -312,15 +316,15 @@ | ||
| 312 | 316 | * @param float|int|string $unixTimestamp Unix Timestamp |
| 313 | 317 | * |
| 314 | 318 | * @return false|float MS Excel serialized date/time value |
| 315 | 319 | */ |
| 316 | - public static function timestampToExcel($unixTimestamp) | |
| 320 | + public static function timestampToExcel($unixTimestamp, ?int $calendar = null) | |
| 317 | 321 | { |
| 318 | 322 | if (!is_numeric($unixTimestamp)) { |
| 319 | 323 | return false; |
| 320 | 324 | } |
| 321 | 325 | |
| 322 | - return self::dateTimeToExcel(new DateTime('@' . $unixTimestamp)); | |
| 326 | + return self::dateTimeToExcel(new DateTime('@' . $unixTimestamp), $calendar); | |
| 323 | 327 | } |
| 324 | 328 | |
| 325 | 329 | /** |
| 326 | 330 | * formattedPHPToExcel. |
| @@ -327,11 +331,12 @@ | ||
| 327 | 331 | * |
| 328 | 332 | * @return float Excel date/time value |
| 329 | 333 | * @param float|int $seconds |
| 330 | 334 | */ |
| 331 | - public static function formattedPHPToExcel(int $year, int $month, int $day, int $hours = 0, int $minutes = 0, $seconds = 0): float | |
| 335 | + public static function formattedPHPToExcel(int $year, int $month, int $day, int $hours = 0, int $minutes = 0, $seconds = 0, ?int $calendar = null): float | |
| 332 | 336 | { |
| 333 | - if (self::$excelCalendar == self::CALENDAR_WINDOWS_1900) { | |
| 337 | + $calendar ??= self::$excelCalendar; | |
| 338 | + if ($calendar === self::CALENDAR_WINDOWS_1900) { | |
| 334 | 339 | // |
| 335 | 340 | // Fudge factor for the erroneous fact that the year 1900 is treated as a Leap Year in MS Excel |
| 336 | 341 | // This affects every date following 28th February 1900 |
| 337 | 342 | // |
| @@ -476,9 +481,9 @@ | ||
| 476 | 481 | * @param string $dateValue Examples: '2009-12-31', '2009-12-31 15:59', '2009-12-31 15:59:10' |
| 477 | 482 | * |
| 478 | 483 | * @return false|float Excel date/time serial value |
| 479 | 484 | */ |
| 480 | - public static function stringToExcel(string $dateValue) | |
| 485 | + public static function stringToExcel(string $dateValue, ?int $calendar = null) | |
| 481 | 486 | { |
| 482 | 487 | if (strlen($dateValue) < 2) { |
| 483 | 488 | return false; |
| 484 | 489 | } |
| @@ -485,9 +490,9 @@ | ||
| 485 | 490 | if (!preg_match('/^(\d{1,4}[ .\/\-][A-Z]{3,9}([ .\/\-]\d{1,4})?|[A-Z]{3,9}[ .\/\-]\d{1,4}([ .\/\-]\d{1,4})?|\d{1,4}[ .\/\-]\d{1,4}([ .\/\-]\d{1,4})?)( \d{1,2}:\d{1,2}(:\d{1,2}([.]\d+)?)?)?$/iu', $dateValue)) { |
| 486 | 491 | return false; |
| 487 | 492 | } |
| 488 | 493 | |
| 489 | - $dateValueNew = DateTimeExcel\DateValue::fromString($dateValue); | |
| 494 | + $dateValueNew = DateTimeExcel\DateValue::fromString2($dateValue, $calendar); | |
| 490 | 495 | |
| 491 | 496 | if (!is_float($dateValueNew)) { |
| 492 | 497 | return false; |
| 493 | 498 | } |