Add support for 1904 dates
This commit adds support for dates using the 1904 calendar (starting 1904-01-01 00:00:00). It also fixes some issues with the dates in 1900 calendar (which now correctly start at 1899-12-30 00:00:00). Finally, it is now possible to have negative timestamps, representing dates before the base date (and up to 0000-01-01 00:00:00), as per the SpreadsheetML specs. Note that some versions of Excel don't support negative dates...
This commit is contained in:
1 parent
e1ae3c8a81
commit
c74c0d9127
9 files changed
+194
-102
No files matched your search
@@ -15,29 +15,51 @@ class CellValueFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
public function dataProviderForTestExcelDate()
|
||||
{
|
||||
return [
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 42429, '2016-02-29 00:00:00'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, '146098', '2299-12-31 00:00:00'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, -700, null],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 0, '1900-01-01 00:00:00'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 0.25, '1900-01-01 06:00:00'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 0.5, '1900-01-01 12:00:00'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 0.75, '1900-01-01 18:00:00'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 0.99999, '1900-01-01 23:59:59'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 1, '1900-01-01 00:00:00'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 59.999988425926, '1900-02-28 23:59:59'],
|
||||
[CellValueFormatter::CELL_TYPE_NUMERIC, 60.458333333333, '1900-02-28 11:00:00'],
|
||||
// use 1904 dates, node value, expected date as string
|
||||
|
||||
// 1900 calendar
|
||||
[false, 3687.4207639, '1910-02-03 10:05:54'],
|
||||
[false, 2.5000000, '1900-01-01 12:00:00'],
|
||||
[false, 2958465.9999884, '9999-12-31 23:59:59'],
|
||||
[false, 2958465.9999885, null],
|
||||
[false, -2337.999989, '1893-08-05 00:00:01'],
|
||||
[false, -693593, '0001-01-01 00:00:00'],
|
||||
[false, -693593.0000001, null],
|
||||
[false, 0, '1899-12-30 00:00:00'],
|
||||
[false, 0.25, '1899-12-30 06:00:00'],
|
||||
[false, 0.5, '1899-12-30 12:00:00'],
|
||||
[false, 0.75, '1899-12-30 18:00:00'],
|
||||
[false, 0.99999, '1899-12-30 23:59:59'],
|
||||
[false, 1, '1899-12-31 00:00:00'],
|
||||
[false, '3687.4207639', '1910-02-03 10:05:54'],
|
||||
|
||||
// 1904 calendar
|
||||
[true, 2225.4207639, '1910-02-03 10:05:54'],
|
||||
[true, 2.5000000, '1904-01-03 12:00:00'],
|
||||
[true, 2957003.9999884, '9999-12-31 23:59:59'],
|
||||
[true, 2957003.9999885, null],
|
||||
[true, -3799.999989, '1893-08-05 00:00:01'],
|
||||
[true, -695055, '0001-01-01 00:00:00'],
|
||||
[true, -695055.0000001, null],
|
||||
[true, 0, '1904-01-01 00:00:00'],
|
||||
[true, 0.25, '1904-01-01 06:00:00'],
|
||||
[true, 0.5, '1904-01-01 12:00:00'],
|
||||
[true, 0.75, '1904-01-01 18:00:00'],
|
||||
[true, 0.99999, '1904-01-01 23:59:59'],
|
||||
[true, 1, '1904-01-02 00:00:00'],
|
||||
[true, '2225.4207639', '1910-02-03 10:05:54'],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @dataProvider dataProviderForTestExcelDate
|
||||
*
|
||||
* @param string $cellType
|
||||
* @param bool $shouldUse1904Dates
|
||||
* @param int|float|string $nodeValue
|
||||
* @param string|null $expectedDateAsString
|
||||
* @return void
|
||||
*/
|
||||
public function testExcelDate($cellType, $nodeValue, $expectedDateAsString)
|
||||
public function testExcelDate($shouldUse1904Dates, $nodeValue, $expectedDateAsString)
|
||||
{
|
||||
$nodeListMock = $this->getMockBuilder('DOMNodeList')->disableOriginalConstructor()->getMock();
|
||||
|
||||
@@ -53,7 +75,7 @@ class CellValueFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
->expects($this->atLeastOnce())
|
||||
->method('getAttribute')
|
||||
->will($this->returnValueMap([
|
||||
[CellValueFormatter::XML_ATTRIBUTE_TYPE, $cellType],
|
||||
[CellValueFormatter::XML_ATTRIBUTE_TYPE, CellValueFormatter::CELL_TYPE_NUMERIC],
|
||||
[CellValueFormatter::XML_ATTRIBUTE_STYLE_ID, 123],
|
||||
]));
|
||||
|
||||
@@ -72,7 +94,7 @@ class CellValueFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
->with(123)
|
||||
->will($this->returnValue(true));
|
||||
|
||||
$formatter = new CellValueFormatter(null, $styleManagerMock, false, new Escaper\XLSX());
|
||||
$formatter = new CellValueFormatter(null, $styleManagerMock, false, $shouldUse1904Dates, new Escaper\XLSX());
|
||||
$result = $formatter->extractAndFormatNodeValue($nodeMock);
|
||||
|
||||
if ($expectedDateAsString === null) {
|
||||
@@ -126,7 +148,7 @@ class CellValueFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
->method('shouldFormatNumericValueAsDate')
|
||||
->will($this->returnValue(false));
|
||||
|
||||
$formatter = new CellValueFormatter(null, $styleManagerMock, false, new Escaper\XLSX());
|
||||
$formatter = new CellValueFormatter(null, $styleManagerMock, false, false, new Escaper\XLSX());
|
||||
$formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatNumericCellValue', $value, 0);
|
||||
|
||||
$this->assertEquals($expectedFormattedValue, $formattedValue);
|
||||
@@ -169,7 +191,7 @@ class CellValueFormatterTest extends \PHPUnit_Framework_TestCase
|
||||
->with(CellValueFormatter::XML_NODE_INLINE_STRING_VALUE)
|
||||
->will($this->returnValue($nodeListMock));
|
||||
|
||||
$formatter = new CellValueFormatter(null, null, false, new Escaper\XLSX());
|
||||
$formatter = new CellValueFormatter(null, null, false, false, new Escaper\XLSX());
|
||||
$formattedValue = \ReflectionHelper::callMethodOnObject($formatter, 'formatInlineStringCellValue', $nodeMock);
|
||||
|
||||
$this->assertEquals($expectedFormattedValue, $formattedValue);
|
||||
|
||||
@@ -231,9 +231,34 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '2015-09-01 22:23:00'),
|
||||
],
|
||||
[
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-02-28 23:59:59'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-02-27 23:59:59'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-03-01 00:00:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-02-28 11:00:00'), // 1900-02-29 should be converted to 1900-02-28
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-02-28 11:00:00'),
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return void
|
||||
*/
|
||||
public function testReadShouldSupportDifferentDatesAsNumericTimestampWith1904Calendar()
|
||||
{
|
||||
// make sure dates are always created with the same timezone
|
||||
date_default_timezone_set('UTC');
|
||||
|
||||
$allRows = $this->getAllRowsForFile('sheet_with_different_numeric_value_dates_1904_calendar.xlsx');
|
||||
|
||||
$expectedRows = [
|
||||
[
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '2019-09-02 00:00:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '2019-09-03 00:00:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '2019-09-02 22:23:00'),
|
||||
],
|
||||
[
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1904-02-29 23:59:59'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1904-03-02 00:00:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1904-03-01 11:00:00'),
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
@@ -251,11 +276,11 @@ class ReaderTest extends \PHPUnit_Framework_TestCase
|
||||
|
||||
$expectedRows = [
|
||||
[
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-01-01 00:00:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-01-01 11:29:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-01-01 23:29:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-01-01 01:42:25'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1900-01-01 13:42:25'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1899-12-30 00:00:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1899-12-30 11:29:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1899-12-30 23:29:00'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1899-12-30 01:42:25'),
|
||||
\DateTime::createFromFormat('Y-m-d H:i:s', '1899-12-30 13:42:25'),
|
||||
],
|
||||
];
|
||||
$this->assertEquals($expectedRows, $allRows);
|
||||
|
||||
Binary file not shown.
Reference in new issue
Block a user