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