PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception

Failed to modify date with interval: $modifier

Error message

Failed to modify date with interval: $modifier

What it means

Date::safeModify() wraps DateTime::modify for Excel-serial conversion (excelToDateTimeObject builds modifiers like '+ N days' from the serial). On PHP < 8.3 a false return from modify() — unparseable or overflowing modifier — throws this message; on PHP >= 8.3 the same failure surfaces as DateMalformedStringException from DateTime itself instead. It therefore fires on out-of-range or absurd Excel timestamps.

Source

Thrown at src/PhpSpreadsheet/Shared/Date.php:639

             * @return bool Returns false if the error is not of type E_WARNING or if the message does not match
             *              the specified condition. Throws PhpSpreadsheetException when conditions are met.
             */
            static function (int $severity, string $message): bool {
                if ($severity !== E_WARNING) {
                    return false;
                }
                if (!str_starts_with($message, 'DateTime::modify()')) {
                    return false;
                }

                throw new PhpSpreadsheetException($message);
            }
        );

        try {
            $result = $dateTime->modify($modifier);
            if ($result === false) {
                throw new PhpSpreadsheetException('Failed to modify date with interval: ' . $modifier);
            }

            return $result;
        } finally {
            restore_error_handler();
        }
    }
}

View on GitHub (pinned to 65b080eef4)

Solutions

  1. Bound-check the serial before converting: valid Excel dates span roughly -693594 (1900) to 2958465 (9999)
  2. Fix the source data or its number format so non-date numbers are not read as dates
  3. Upgrade to PHP 8.3+ where the failure mode is the clearer DateMalformedStringException
  4. Wrap read loops in try/catch on PhpSpreadsheet\Exception and log the cell coordinate

Example fix

// before
$dt = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($cellValue); // huge serial throws

// after
if ($cellValue < -693594 || $cellValue > 2958465) {
    throw new \InvalidArgumentException("Not a valid Excel date serial: $cellValue");
}
$dt = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($cellValue);
Defensive patterns

Strategy: validation

Validate before calling

const EXCEL_SERIAL_MIN = -693594; // 1900-01-01
const EXCEL_SERIAL_MAX = 2958465;  // 9999-12-31

function isPlausibleExcelSerial(mixed $value): bool
{
    return is_int($value) || is_float($value)
        ? $value >= EXCEL_SERIAL_MIN && $value <= EXCEL_SERIAL_MAX
        : false;
}

Try / catch

try {
    $dt = \PhpOffice\PhpSpreadsheet\Shared\Date::excelToDateTimeObject($serial);
} catch (\PhpOffice\PhpSpreadsheet\Exception | \DateMalformedStringException $e) {
    // PHP<8.3 throws the former, PHP>=8.3 the latter
    $dt = null; // treat cell as non-date
}

Prevention

When it happens

Trigger: Calling Date::excelToDateTimeObject()/excelToTimestamp() with an astronomical serial (e.g. 3172011706730017, the value cited in the source comment); reading a cell whose numeric garbage carries a date number format so the value gets converted; extreme microsecond adjustments on the PHPToExcel path (Date.php:569).

Common situations: Columns mixing real dates with typed numbers (20250101) or formula blowups formatted as dates; corrupted cells; data-entry errors in date-formatted columns from third-party reports.

Related errors


AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17). Data as JSON: /api/errors/782ad96c52c6b05f. Report an issue: GitHub.