diff --git a/src/PhpSpreadsheet/Cell/Cell.php b/src/PhpSpreadsheet/Cell/Cell.php index 5a9def37..a4d74daf 100644 --- a/src/PhpSpreadsheet/Cell/Cell.php +++ b/src/PhpSpreadsheet/Cell/Cell.php @@ -2,10 +2,12 @@ namespace PhpOffice\PhpSpreadsheet\Cell; +use DateTime; use PhpOffice\PhpSpreadsheet\Calculation\Calculation; use PhpOffice\PhpSpreadsheet\Collection\Cells; use PhpOffice\PhpSpreadsheet\Exception; use PhpOffice\PhpSpreadsheet\RichText\RichText; +use PhpOffice\PhpSpreadsheet\Shared\Date as SharedDate; use PhpOffice\PhpSpreadsheet\Style\NumberFormat; use PhpOffice\PhpSpreadsheet\Style\Style; use PhpOffice\PhpSpreadsheet\Worksheet\Worksheet; @@ -234,6 +236,22 @@ class Cell case DataType::TYPE_BOOL: $this->value = (bool) $value; + break; + case DataType::TYPE_ISO_DATE: + if (!is_string($value)) { + throw new Exception('Non-string supplied for datatype Date'); + } + $date = new DateTime($value); + $newValue = SharedDate::PHPToExcel($date); + if ($newValue === false) { + throw new Exception("Invalid string $value supplied for datatype Date"); + } + if (preg_match('/^\\d\\d:\\d\\d:\\d\\d/', $value) == 1) { + $newValue = fmod($newValue, 1.0); + } + $this->value = $newValue; + $dataType = DataType::TYPE_NUMERIC; + break; case DataType::TYPE_ERROR: $this->value = DataType::checkErrorCode($value); diff --git a/src/PhpSpreadsheet/Cell/DataType.php b/src/PhpSpreadsheet/Cell/DataType.php index cee3e1e5..0f7efe2a 100644 --- a/src/PhpSpreadsheet/Cell/DataType.php +++ b/src/PhpSpreadsheet/Cell/DataType.php @@ -16,6 +16,7 @@ class DataType const TYPE_NULL = 'null'; const TYPE_INLINE = 'inlineStr'; const TYPE_ERROR = 'e'; + const TYPE_ISO_DATE = 'd'; /** * List of error codes. diff --git a/src/PhpSpreadsheet/Shared/Date.php b/src/PhpSpreadsheet/Shared/Date.php index 5b0a2907..b4cf1913 100644 --- a/src/PhpSpreadsheet/Shared/Date.php +++ b/src/PhpSpreadsheet/Shared/Date.php @@ -228,7 +228,7 @@ class Date * @param mixed $dateValue PHP DateTime object or a string - Unix timestamp is also permitted, but discouraged; * not Y2038-safe on a 32-bit system, and no timezone info * - * @return bool|float Excel date/time value + * @return false|float Excel date/time value * or boolean FALSE on failure */ public static function PHPToExcel($dateValue) diff --git a/tests/PhpSpreadsheetTests/Reader/Xlsx/ExplicitDateTest.php b/tests/PhpSpreadsheetTests/Reader/Xlsx/ExplicitDateTest.php new file mode 100644 index 00000000..23af5222 --- /dev/null +++ b/tests/PhpSpreadsheetTests/Reader/Xlsx/ExplicitDateTest.php @@ -0,0 +1,52 @@ +2021-12-31T23:44:51.894', $data); + self::assertStringContainsString('2021-12-31', $data); + self::assertStringContainsString('23:44:51.894', $data); + } + } + + public static function testExplicitDate(): void + { + $spreadsheet = IOFactory::load(self::$testbook); + $sheet = $spreadsheet->getActiveSheet(); + // DateTime + $value = $sheet->getCell('A3')->getValue(); + $formatted = $sheet->getCell('A3')->getFormattedValue(); + self::assertEqualsWithDelta(44561.98948, $value, 0.00001); + self::assertSame('2021-12-31 23:44:51', $formatted); + // Date only + $value = $sheet->getCell('B3')->getValue(); + $formatted = $sheet->getCell('B3')->getFormattedValue(); + self::assertEquals(44561, $value); + self::assertSame('2021-12-31', $formatted); + // Time only + $value = $sheet->getCell('C3')->getValue(); + $formatted = $sheet->getCell('C3')->getFormattedValue(); + self::assertEqualsWithDelta(0.98948, $value, 0.00001); + self::assertSame('23:44:51', $formatted); + + $spreadsheet->disconnectWorksheets(); + } +} diff --git a/tests/data/Reader/XLSX/explicitdate.xlsx b/tests/data/Reader/XLSX/explicitdate.xlsx new file mode 100644 index 00000000..c4017b87 Binary files /dev/null and b/tests/data/Reader/XLSX/explicitdate.xlsx differ