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
- Bound-check the serial before converting: valid Excel dates span roughly -693594 (1900) to 2958465 (9999)
- Fix the source data or its number format so non-date numbers are not read as dates
- Upgrade to PHP 8.3+ where the failure mode is the clearer DateMalformedStringException
- 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
- Range-check serials before conversion, especially from date-formatted columns
- Clean columns that mix real dates with typed numbers like 20250101
- Test date conversions against your max data values on the target PHP version
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
- Invalid value $calculateDateTimeType for calculated date tim
- Invalid timezone
- Non-string value supplied for Iso Date conversion
- Invalid string $value supplied for datatype Date
- Rows or columns overflow! Excel5 has limit to 65535 rows and
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/782ad96c52c6b05f.
Report an issue: GitHub.