Skip to content

Non-backwards compatible rounding issue in 2.0.0 - DateTime #3899

@BGehrels

Description

@BGehrels

This is:

- [x] a bug report
- [ ] a feature request
- [ ] **not** a usage question (ask them on https://stackoverflow.com/questions/tagged/phpspreadsheet or https://gitter.im/PHPOffice/PhpSpreadsheet)

What is the expected behavior?

When i persist and reread an excel sheet, the data within the read version should be the same as the data persisted.
This has been the case with 1.x, but it is not with 2.0.0 if Date::excelToDateTimeObject / Date::dateTimeToExcel is used

What is the current behavior?

When i use Date::dateTimeToExcel to write a DateTime in to a Cell, and then immediately reread it from the in-memory spreadsheet using Date::excelToDateTimeObject, then it works fine.

If i persist it to a file and reread it from there it will be slightly off:

-2020-10-21T14:55:31.000000+0000
+2020-10-21T14:55:30.999994+0000

If you throw away milliseconds afterwards, for example during database persistence, as you end up a second off (which can land you in another hour of the day, another aggregation bucket, and so on)

What are the steps to reproduce?

The test posted below works fine in 1.29.0x, but not in 2.0.0

Please provide a Minimal, Complete, and Verifiable example of code that exhibits the issue without relying on an external Excel file or a web server:

<?php

use PHPUnit\Framework\TestCase;
use DateTime;
use PhpOffice\PhpSpreadsheet\Shared\Date;
use PhpOffice\PhpSpreadsheet\Spreadsheet;
use PhpOffice\PhpSpreadsheet\Writer\Xlsx;

class ExcelDateTimeOfByOneErrorTest extends TestCase
{
    public function testThatDateTimesCanBePersistedAndReread(): void
    {
        $originalDateTime = new DateTime('2020-10-21T14:55:31');

        $dateTimeFromSpreadsheet = $this->getDateTimeFrom($this->excelSheetWithDateTime($originalDateTime));
        $dateTimeFromSpreadsheetAfterPersistAndReread = $this->getDateTimeFrom($this->persistAndReread($this->excelSheetWithDateTime($originalDateTime)));

        static::assertEquals($originalDateTime, $dateTimeFromSpreadsheet);
        static::assertEquals($originalDateTime, $dateTimeFromSpreadsheetAfterPersistAndReread);
    }

    private function excelSheetWithDateTime(DateTime $dateTime): Spreadsheet
    {
        $spreadsheet = new Spreadsheet();
        $spreadsheet->getActiveSheet()->setCellValue('A1', Date::dateTimeToExcel($dateTime));
        return $spreadsheet;
    }

    public function getDateTimeFrom(Spreadsheet $spreadsheet): DateTime
    {
        return Date::excelToDateTimeObject($spreadsheet->getSheet(0)->getCell('A1')->getCalculatedValue());
    }

    private function persistAndReread(Spreadsheet $spreadsheet): Spreadsheet
    {
        $temp_pointer = tmpfile();
        $tempFileName = stream_get_meta_data($temp_pointer)['uri'];
        (new Xlsx($spreadsheet))->save($tempFileName);
        return (new \PhpOffice\PhpSpreadsheet\Reader\Xlsx())->load($tempFileName);
    }

}

What features do you think are causing the issue

  • Reader
  • Writer
  • Styles
  • Data Validations
  • Formula Calculations
  • Charts
  • AutoFilter
  • Form Elements

Does an issue affect all spreadsheet file formats? If not, which formats are affected?

Only tested Xlsx

Which versions of PhpSpreadsheet and PHP are affected?

2.0.0 is affected, 1.29.0 is not affected.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions