Micro-optimization for excelToDateTimeObject

Fix #4438. Do some optimization if Excel value is an integer. This is unlikely to make much of a difference, but the use case seems pretty common (cell represents a date rather than date-time), so we may as well do it. There had been no tests for negative integer values, because Excel does not handle those well, but OpenOffice and Gnumeric handle them just fine, so add some tests for them.
This commit is contained in:
oleibman
2025-04-13 14:43:16 -07:00
parent 86cca1230a
commit 5c6f2d0e34
2 changed files with 34 additions and 4 deletions
+7
View File
@@ -214,6 +214,13 @@ class Date
$baseDate = new DateTime('1899-12-30', $timeZone);
}
if (is_int($excelTimestamp)) {
if ($excelTimestamp >= 0) {
return $baseDate->modify("+ $excelTimestamp days");
}
return $baseDate->modify("$excelTimestamp days");
}
$days = floor($excelTimestamp);
$partDay = $excelTimestamp - $days;
$hms = 86400 * $partDay;
@@ -4,17 +4,22 @@ declare(strict_types=1);
namespace PhpOffice\PhpSpreadsheetTests\Style;
use PhpOffice\PhpSpreadsheet\Calculation\Functions;
use PhpOffice\PhpSpreadsheet\Shared\StringHelper;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat;
use PhpOffice\PhpSpreadsheet\Style\NumberFormat\NumberFormatter;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
class NumberFormatTest extends TestCase
{
private string $compatibilityMode;
protected function setUp(): void
{
StringHelper::setDecimalSeparator('.');
StringHelper::setThousandsSeparator(',');
$this->compatibilityMode = Functions::getCompatibilityMode();
}
protected function tearDown(): void
@@ -22,12 +27,13 @@ class NumberFormatTest extends TestCase
StringHelper::setCurrencyCode(null);
StringHelper::setDecimalSeparator(null);
StringHelper::setThousandsSeparator(null);
Functions::setCompatibilityMode($this->compatibilityMode);
}
/**
* @param null|bool|float|int|string $args string to be formatted
*/
#[\PHPUnit\Framework\Attributes\DataProvider('providerNumberFormat')]
#[DataProvider('providerNumberFormat')]
public function testFormatValueWithMask(mixed $expectedResult, mixed ...$args): void
{
$result = NumberFormat::toFormattedString(...$args);
@@ -42,7 +48,7 @@ class NumberFormatTest extends TestCase
/**
* @param null|bool|float|int|string $args string to be formatted
*/
#[\PHPUnit\Framework\Attributes\DataProvider('providerNumberFormatFractions')]
#[DataProvider('providerNumberFormatFractions')]
public function testFormatValueWithMaskFraction(mixed $expectedResult, mixed ...$args): void
{
$result = NumberFormat::toFormattedString(...$args);
@@ -57,7 +63,7 @@ class NumberFormatTest extends TestCase
/**
* @param null|bool|float|int|string $args string to be formatted
*/
#[\PHPUnit\Framework\Attributes\DataProvider('providerNumberFormatDates')]
#[DataProvider('providerNumberFormatDates')]
public function testFormatValueWithMaskDate(mixed $expectedResult, mixed ...$args): void
{
$result = NumberFormat::toFormattedString(...$args);
@@ -69,6 +75,23 @@ class NumberFormatTest extends TestCase
return require 'tests/data/Style/NumberFormatDates.php';
}
public function testDatesOpenOfficeGnumericNonPositive(): void
{
Functions::setCompatibilityMode(
Functions::COMPATIBILITY_OPENOFFICE
);
$fmt1 = 'yyyy-mm-dd';
$rslt = NumberFormat::toFormattedString(0, $fmt1);
self::assertSame('1899-12-30', $rslt);
$rslt = NumberFormat::toFormattedString(-2, $fmt1);
self::assertSame('1899-12-28', $rslt);
$rslt = NumberFormat::toFormattedString(-2.4, $fmt1);
self::assertSame('1899-12-27', $rslt);
$fmt2 = 'yyyy-mm-dd hh:mm:ss AM/PM';
$rslt = NumberFormat::toFormattedString(-2.4, $fmt2);
self::assertSame('1899-12-27 02:24:00 PM', $rslt);
}
public function testCurrencyCode(): void
{
// "Currency symbol" replaces $ in some cases, not in others
@@ -83,7 +106,7 @@ class NumberFormatTest extends TestCase
StringHelper::setCurrencyCode($cur);
}
#[\PHPUnit\Framework\Attributes\DataProvider('providerNoScientific')]
#[DataProvider('providerNoScientific')]
public function testNoScientific(string $expectedResult, string $numericString): void
{
$result = NumberFormatter::floatStringConvertScientific($numericString);