{"record":{"id":"c5da8a61f0a7ef19","repo":"DenverCoder1/github-readme-streak-stats","slug":"400-invalid-timezone","errorCode":"400","errorMessage":"Invalid timezone.","messagePattern":"Invalid timezone\\.","errorType":"validation","errorClass":"InvalidArgumentException","httpStatus":400,"severity":"error","filePath":"src/stats.php","lineNumber":296,"sourceCode":"            }\n        }\n    }\n    return $contributions;\n}\n\n/**\n * Get the current date for a requested timezone.\n *\n * @param string $timezone Timezone identifier, or empty for the server default\n * @param DateTimeImmutable|null $now Current time override for tests\n * @return string Current date in Y-m-d format\n */\nfunction getCurrentDate(string $timezone = \"\", ?DateTimeImmutable $now = null): string\n{\n    try {\n        $dateTimezone = new DateTimeZone($timezone ?: date_default_timezone_get());\n    } catch (Exception) {\n        throw new InvalidArgumentException(\"Invalid timezone.\", 400);\n    }\n\n    $now = $now ?: new DateTimeImmutable(\"now\");\n    return $now->setTimezone($dateTimezone)->format(\"Y-m-d\");\n}\n\n/**\n * Normalize names of days of the week (eg. [\"Sunday\", \" mon\", \"TUE\"] -> [\"Sun\", \"Mon\", \"Tue\"])\n *\n * @param array<string> $days List of days of the week\n * @return array<string> List of normalized days of the week\n */\nfunction normalizeDays(array $days): array\n{\n    return array_filter(\n        array_map(function ($dayOfWeek) {\n            // trim whitespace, capitalize first letter only, return first 3 characters\n            $dayOfWeek = substr(ucfirst(strtolower(trim($dayOfWeek))), 0, 3);","sourceCodeStart":278,"sourceCodeEnd":314,"githubUrl":"https://github.com/DenverCoder1/github-readme-streak-stats/blob/70dd50f921097927dc8314ac33a04b010a09924d/src/stats.php#L278-L314","documentation":"getCurrentDate() resolves the current date (Y-m-d) in a caller-supplied timezone. The timezone string is passed straight to PHP's DateTimeZone constructor; when it is not a recognized timezone identifier, the constructor throws and the library re-throws it as an InvalidArgumentException with HTTP-style code 400. This lets callers distinguish bad user input (e.g. an invalid tz query parameter) from internal failures.","triggerScenarios":"Calling getCurrentDate() (directly or via stats endpoints that accept a timezone parameter) with a string that is not a valid IANA timezone identifier or UTC offset, e.g. 'America/New York', 'EST' where abbreviation support is unavailable, an empty-but-whitespace string that bypasses the '' fallback, or a typo like 'Europe/Londonn'.","commonSituations":"Passing user-supplied timezone query parameters straight through without validation; legacy timezone abbreviations ('PST', 'CET') that DateTimeZone rejects as identifiers; config files carrying hand-edited timezone values; locale migration where an old app stored Windows timezone names ('Pacific Standard Time') instead of IANA names ('America/Los_Angeles').","solutions":["Validate the timezone against DateTimeZone::listIdentifiers() (or @timezone_identification_list) before calling getCurrentDate().","Use full IANA identifiers like 'America/New_York' instead of abbreviations or Windows timezone names.","Convert Windows timezone names with intl's timezone translation if the input originates from a Windows/ .NET system.","If the parameter is optional, pass an empty string to fall back to date_default_timezone_get() rather than a placeholder value."],"exampleFix":"// before\n$date = getCurrentDate($_GET['tz'] ?? 'America/New York');\n// after\n$tz = $_GET['tz'] ?? '';\nif ($tz !== '' && !in_array($tz, DateTimeZone::listIdentifiers(), true)) {\n    $tz = '';\n}\n$date = getCurrentDate($tz);","handlingStrategy":"validation","validationCode":"function isValidTimezone(string $tz): bool {\n    return $tz === '' || in_array($tz, DateTimeZone::listIdentifiers(), true);\n}\nif (!isValidTimezone($timezone)) {\n    throw new InvalidArgumentException('Unsupported timezone: ' . $timezone);\n}","typeGuard":"function isKnownTimezone(mixed $tz): bool {\n    return is_string($tz) && in_array($tz, DateTimeZone::listIdentifiers(), true);\n}","tryCatchPattern":"try {\n    $date = getCurrentDate($timezone);\n} catch (InvalidArgumentException $e) {\n    if ($e->getCode() === 400) {\n        http_response_code(400);\n        echo json_encode(['error' => 'Invalid timezone supplied']);\n    } else {\n        throw $e;\n    }\n}","preventionTips":["Only pass IANA identifiers (DateTimeZone::listIdentifiers()) — never abbreviations or Windows names.","Validate user-supplied timezone parameters at the request boundary before any date math.","Prefer passing '' to use the server default instead of guessing a timezone string.","Normalize input (trim, exact case) since identifiers are case- and whitespace-sensitive."],"tags":["php","timezone","invalid-argument"],"backgroundTag":"invalid-argument-value","analyzedSha":"70dd50f921097927dc8314ac33a04b010a09924d","analyzedAt":"2026-09-15T02:40:51.909Z","contentChangedAt":"2026-09-15T02:40:51.909Z","schemaVersion":2},"datasetVersion":"2026-09-15T23:17:13.987Z"}