PHPOffice/PhpSpreadsheet · error · PhpOffice\PhpSpreadsheet\Exception
Invalid timezone {$timezoneName}
Error message
Invalid timezone {$timezoneName} What it means
Thrown by TimeZone::getTimeZoneAdjustment() when the timezone name supplied (or the globally configured one via TimeZone::setTimeZone()) fails validateTimeZone(). The method then builds a DateTimeZone, which requires a valid IANA zone identifier (e.g. 'Europe/Paris', 'UTC'); abbreviations like 'CST' or made-up strings are rejected.
Source
Thrown at src/PhpSpreadsheet/Shared/TimeZone.php:69
{
return self::$timezone;
}
/**
* Return the Timezone offset used for date/time conversions to/from UST
* This requires both the timezone and the calculated date/time to allow for local DST.
*
* @param ?string $timezoneName The timezone for finding the adjustment to UST
* @param float|int $timestamp PHP date/time value
*
* @return int Number of seconds for timezone adjustment
*/
public static function getTimeZoneAdjustment(?string $timezoneName, $timestamp): int
{
$timezoneName = $timezoneName ?? self::$timezone;
$dtobj = Date::dateTimeFromTimestamp("$timestamp");
if (!self::validateTimeZone($timezoneName)) {
throw new PhpSpreadsheetException("Invalid timezone $timezoneName");
}
$dtobj->setTimeZone(new DateTimeZone($timezoneName));
return $dtobj->getOffset();
}
}
View on GitHub (pinned to 65b080eef4)
Solutions
- Use full IANA identifiers everywhere ('America/New_York', 'Europe/Berlin', 'UTC') and normalize input before use.
- Check the setter's return: if (!TimeZone::setTimeZone($tz)) { /* reject */ } — never ignore it, since the failure converts into this later exception.
- Validate user-supplied names against DateTimeZone::listIdentifiers() (or TimeZone::validateTimeZone()) at the input boundary and keep a safe default.
- Catch PhpSpreadsheetException around date-heavy export code and map it to a configuration error message naming the bad timezone.
Example fix
// before
\PhpOffice\PhpSpreadsheet\Shared\TimeZone::setTimeZone('CST'); // returns false, ignored
$adjust = \PhpOffice\PhpSpreadsheet\Shared\TimeZone::getTimeZoneAdjustment(null, $ts);
// Invalid timezone CST
// after
$tz = in_array($userTz, DateTimeZone::listIdentifiers(), true) ? $userTz : 'UTC';
if (!\PhpOffice\PhpSpreadsheet\Shared\TimeZone::setTimeZone($tz)) {
throw new RuntimeException("Unusable timezone: $tz");
} Defensive patterns
Strategy: validation
Validate before calling
$valid = in_array($tzName, DateTimeZone::listIdentifiers(), true)
|| $tzName === 'UTC';
if (!$valid) { $tzName = 'UTC'; /* or reject */ }
$adjust = \PhpOffice\PhpSpreadsheet\Shared\TimeZone::getTimeZoneAdjustment($tzName, $ts); Type guard
function validTimeZoneOrNull(?string $tz): ?string
{
return ($tz !== null && (TimeZone::validateTimeZone($tz) || in_array($tz, DateTimeZone::listIdentifiers(), true)))
? $tz : null; // null → caller uses safe default
} Try / catch
try { $adjust = TimeZone::getTimeZoneAdjustment($tzName, $ts); }
catch (\PhpOffice\PhpSpreadsheet\Exception $e) {
if (str_contains($e->getMessage(), 'Invalid timezone')) {
$adjust = TimeZone::getTimeZoneAdjustment('UTC', $ts); // safe fallback
} else { throw $e; }
} Prevention
- Store and accept only IANA identifiers ('Europe/Berlin'), never abbreviations like 'CST' or offsets like 'GMT+2'.
- Never ignore the boolean return of TimeZone::setTimeZone() — a silent false becomes this exception later.
- Validate timezone strings at the input boundary (user profiles, config) with DateTimeZone::listIdentifiers().
When it happens
Trigger: Calling TimeZone::getTimeZoneAdjustment($tzName, $timestamp) directly, or after TimeZone::setTimeZone($bad) — note setTimeZone() itself only returns false on a bad name, so a silent failure there resurfaces as this exception at adjustment time. Typical bad inputs: 'CST', 'GMT+2', 'Eastern', trailing whitespace, or null falling back to a default that was never configured.
Common situations: Feeding user-profile timezone strings or $_POST/DB values straight into the API; config files with 'timezone: EST' instead of IANA names; setTimeZone() return value ignored so the bad value persists until a date conversion runs.
Related errors
- Invalid value $calculateDateTimeType for calculated date tim
- Valid directory to TrueType Font files not specified
- Unknown font name "$name". Cannot map to TrueType font file
- Directory does not exist: $cacheDirectory
- Line ending must be \n (Unix) or \r\n (Windows)
AI-assisted analysis of PHPOffice/PhpSpreadsheet@65b080eef4 (2026-08-17).
Data as JSON: /api/errors/4ffa11c64bb19a06.
Report an issue: GitHub.