{"record":{"id":"351fa477bc202ae1","repo":"PHPOffice/PhpSpreadsheet","slug":"invalid-timezone","errorCode":null,"errorMessage":"Invalid timezone","messagePattern":"Invalid timezone","errorType":"exception","errorClass":"PhpOffice\\PhpSpreadsheet\\Exception","httpStatus":null,"severity":"error","filePath":"src/PhpSpreadsheet/Shared/Date.php","lineNumber":155,"sourceCode":"    }\n\n    /**\n     * Validate a timezone.\n     *\n     * @param null|DateTimeZone|string $timeZone The timezone to validate, either as a timezone string or object\n     *\n     * @return ?DateTimeZone The timezone as a timezone object\n     */\n    private static function validateTimeZone($timeZone): ?DateTimeZone\n    {\n        if ($timeZone instanceof DateTimeZone || $timeZone === null) {\n            return $timeZone;\n        }\n        if (in_array($timeZone, DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC))) {\n            return new DateTimeZone($timeZone);\n        }\n\n        throw new PhpSpreadsheetException('Invalid timezone');\n    }\n\n    /**\n     * @param mixed $value Converts a date/time in ISO-8601 standard format date string to an Excel\n     *                         serialized timestamp.\n     *                     See https://en.wikipedia.org/wiki/ISO_8601 for details of the ISO-8601 standard format.\n     */\n    public static function convertIsoDate(mixed $value, ?int $calendar = null): float|int\n    {\n        if (!is_string($value)) {\n            throw new Exception('Non-string value supplied for Iso Date conversion');\n        }\n\n        $date = new DateTime($value);\n        $dateErrors = DateTime::getLastErrors();\n\n        if (is_array($dateErrors) && ($dateErrors['warning_count'] > 0 || $dateErrors['error_count'] > 0)) {\n            throw new Exception(\"Invalid string $value supplied for datatype Date\");","sourceCodeStart":137,"sourceCodeEnd":173,"githubUrl":"https://github.com/PHPOffice/PhpSpreadsheet/blob/65b080eef4d9fd11a5796135ab145883e5c3d6a6/src/PhpSpreadsheet/Shared/Date.php#L137-L173","documentation":"Date::validateTimeZone() accepts a DateTimeZone, null, or a string that must be one of DateTimeZone::listIdentifiers(DateTimeZone::ALL_WITH_BC); anything else throws 'Invalid timezone'. It is reached publicly via Date::excelToDateTimeObject($ts, $timeZone) (src/PhpSpreadsheet/Shared/Date.php:200), which does not catch it; note Date::setDefaultTimezone() swallows the same exception and returns false instead.","triggerScenarios":"Date::excelToDateTimeObject(44562, 'UTC+2') or 'GMT+2', '+02:00', 'CT', 'EST' — offsets and abbreviations are not IANA identifiers and are not in the list; a typo'd identifier like 'Europe/Berline'.","commonSituations":"Copying timezone strings from JavaScript (moment/Intl offsets), DB timezone offsets, or user-profile '+HH:MM' values straight into the API; mixing setDefaultTimezone (returns bool) with per-call timezone arguments.","solutions":["Pass an IANA identifier: 'Europe/Berlin', 'America/New_York', or 'UTC'","For offsets, construct the object yourself and pass the instance: new DateTimeZone('+02:00') — instances are returned as-is by validateTimeZone","Check the return value of Date::setDefaultTimeZone(); false means the same validation failed","Validate strings against DateTimeZone::listIdentifiers() before calling"],"exampleFix":"// before\n$dt = \\PhpOffice\\PhpSpreadsheet\\Shared\\Date::excelToDateTimeObject(44562, 'UTC+2'); // throws\n\n// after\n$tz = new \\DateTimeZone('+02:00'); // numeric offsets are valid on the object\n$dt = \\PhpOffice\\PhpSpreadsheet\\Shared\\Date::excelToDateTimeObject(44562, $tz);","handlingStrategy":"validation","validationCode":"use PhpOffice\\PhpSpreadsheet\\Shared\\Date;\n\nfunction normalizeTz(string|\\DateTimeZone|null $tz): ?\\DateTimeZone\n{\n    if ($tz instanceof \\DateTimeZone || $tz === null) {\n        return $tz;\n    }\n    if (in_array($tz, \\DateTimeZone::listIdentifiers(\\DateTimeZone::ALL_WITH_BC), true)) {\n        return new \\DateTimeZone($tz);\n    }\n\n    return new \\DateTimeZone('UTC'); // or reject\n}\n\n$dt = Date::excelToDateTimeObject($serial, normalizeTz($userTz));","typeGuard":"function isValidTimeZoneName(string $tz): bool\n{\n    return in_array($tz, \\DateTimeZone::listIdentifiers(\\DateTimeZone::ALL_WITH_BC), true);\n}","tryCatchPattern":null,"preventionTips":["Pass IANA identifiers or DateTimeZone instances, never offsets like 'UTC+2'","Check Date::setDefaultTimeZone()'s bool return — it does not throw","Centralize timezone normalization for user-provided settings"],"tags":["date","timezone","argument-validation"],"backgroundTag":"invalid-timezone","analyzedSha":"65b080eef4d9fd11a5796135ab145883e5c3d6a6","analyzedAt":"2026-08-17T05:40:41.646Z","schemaVersion":2},"datasetVersion":"2026-08-17T09:17:11.063Z"}