mirror of
https://github.com/PHPOffice/PhpSpreadsheet.git
synced 2026-09-06 07:29:05 +00:00
Slight Improvement in Ods Reader Date Handling
Based on recent discussions in #2938, it can do a bit better with date cells that do not use a recognized date style. Improve differentiating `date` from `date+time`, and in deciding whether 4-digit years have been used in the input cells. This causes a change to one test, where the old result incorrectly expected a 2-digit year (you can verify by opening the spreadsheet in question that it is saved with a 4-digit year).
This commit is contained in:
@@ -1081,17 +1081,18 @@ class Ods extends BaseReader
|
||||
$type = DataType::TYPE_NUMERIC;
|
||||
$value = $cellData->getAttributeNS($officeNs, 'date-value');
|
||||
$dataValue = Date::convertIsoDate($value);
|
||||
$format15 = Preg::isMatch('/\d\d\d\d/', $allCellDataText) ? NumberFormat::FORMAT_DATE_XLSX15_YYYY : NumberFormat::FORMAT_DATE_XLSX15;
|
||||
|
||||
if (Preg::isMatch('/^\d\d\d\d-\d\d-\d\d$/', $allCellDataText)) {
|
||||
$formatting = 'yyyy-mm-dd';
|
||||
} elseif (Preg::isMatch('/^\d\d?-[a-zA-Z]+-\d\d\d\d$/', $allCellDataText)) {
|
||||
$formatting = 'd-mmm-yyyy';
|
||||
} elseif ($dataValue != floor($dataValue)) {
|
||||
$formatting = NumberFormat::FORMAT_DATE_XLSX15
|
||||
} elseif ($dataValue != floor($dataValue) || str_contains($allCellDataText, ':')) {
|
||||
$formatting = $format15
|
||||
. ' '
|
||||
. NumberFormat::FORMAT_DATE_TIME4;
|
||||
} else {
|
||||
$formatting = NumberFormat::FORMAT_DATE_XLSX15;
|
||||
$formatting = $format15;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
@@ -75,4 +75,55 @@ class NumberFormatCallbackTest extends TestCase
|
||||
|
||||
return $retVal;
|
||||
}
|
||||
|
||||
public function testMmmdyyyy(): void
|
||||
{
|
||||
$spreadsheetOld = new Spreadsheet();
|
||||
$sheet = $spreadsheetOld->getActiveSheet();
|
||||
$sheet->getCell('A1')->setValue(46000); // Dec 9, 2025
|
||||
$sheet->getStyle('A1')
|
||||
->getNumberFormat()
|
||||
->setFormatCode('mmm d, yyyy');
|
||||
$sheet->getCell('A2')->setValue(46000); // Dec 9, 2025
|
||||
$sheet->getStyle('A2')
|
||||
->getNumberFormat()
|
||||
->setFormatCode(
|
||||
NumberFormat::FORMAT_DATE_DATETIME_BETTER
|
||||
);
|
||||
$writer = new OdsWriter($spreadsheetOld);
|
||||
$this->tempfile = File::temporaryFileName();
|
||||
$writer = new OdsWriter($spreadsheetOld);
|
||||
$writer->useAdditionalNumberFormats([
|
||||
'mmm d, yyyy' => self::mmmdyyyy(...),
|
||||
]);
|
||||
$writer->save($this->tempfile);
|
||||
$spreadsheetOld->disconnectWorksheets();
|
||||
$reader = new OdsReader();
|
||||
$spreadsheet = $reader->load($this->tempfile);
|
||||
$newSheet = $spreadsheet->getActiveSheet();
|
||||
// no formatCallback used, so we can't duplicate custom format,
|
||||
// but we will use a similar format,
|
||||
// with same number of year digits as was written
|
||||
self::assertSame('9-Dec-2025', $newSheet->getCell('A1')->getFormattedValue());
|
||||
self::assertSame('9-Dec-2025 0:00:00', $newSheet->getCell('A2')->getFormattedValue());
|
||||
$spreadsheet->disconnectWorksheets();
|
||||
}
|
||||
|
||||
private static function mmmdyyyy(Style $obj, string $name): void
|
||||
{
|
||||
$writer = $obj->getWriter();
|
||||
$writer->startElement('number:date-style');
|
||||
$writer->writeAttribute('style:name', $name);
|
||||
$writer->startElement('number:month');
|
||||
$writer->writeAttribute('number:textual', 'true');
|
||||
$writer->endElement(); // number:month
|
||||
$writer->writeElement('number:text', ' ');
|
||||
$writer->startElement('number:day');
|
||||
$writer->endElement(); // number:day
|
||||
$writer->writeElement('number:text', ', ');
|
||||
$writer->startElement('number:year');
|
||||
$writer->writeAttribute('number:style', 'long');
|
||||
$writer->endElement(); // number:year
|
||||
$writer->endElement(); // number:date-style
|
||||
}
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ class OdsTest extends TestCase
|
||||
self::assertEquals(0, $firstSheet->getCell('G10')->getValue());
|
||||
|
||||
self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A10')->getDataType()); // Date
|
||||
self::assertEquals('19-Dec-60', $firstSheet->getCell('A10')->getFormattedValue());
|
||||
self::assertEquals('19-Dec-1960', $firstSheet->getCell('A10')->getFormattedValue());
|
||||
|
||||
self::assertEquals(DataType::TYPE_NUMERIC, $firstSheet->getCell('A13')->getDataType()); // Time
|
||||
self::assertEquals('2:30:00', $firstSheet->getCell('A13')->getFormattedValue());
|
||||
|
||||
Reference in New Issue
Block a user