{"record":{"id":"b3b25da094af5419","repo":"python/cpython","slug":"second-must-be-in-0-59-not-second","errorCode":null,"errorMessage":"second must be in 0..59, not {second}","messagePattern":"second must be in 0\\.\\.59, not (.+?)","errorType":"exception","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"Lib/_pydatetime.py","lineNumber":591,"sourceCode":"        raise ValueError(f\"year must be in {MINYEAR}..{MAXYEAR}, not {year}\")\n    if not 1 <= month <= 12:\n        raise ValueError(f\"month must be in 1..12, not {month}\")\n    dim = _days_in_month(year, month)\n    if not 1 <= day <= dim:\n        raise ValueError(f\"day {day} must be in range 1..{dim} for month {month} in year {year}\")\n    return year, month, day\n\ndef _check_time_fields(hour, minute, second, microsecond, fold):\n    hour = _index(hour)\n    minute = _index(minute)\n    second = _index(second)\n    microsecond = _index(microsecond)\n    if not 0 <= hour <= 23:\n        raise ValueError(f\"hour must be in 0..23, not {hour}\")\n    if not 0 <= minute <= 59:\n        raise ValueError(f\"minute must be in 0..59, not {minute}\")\n    if not 0 <= second <= 59:\n        raise ValueError(f\"second must be in 0..59, not {second}\")\n    if not 0 <= microsecond <= 999999:\n        raise ValueError(f\"microsecond must be in 0..999999, not {microsecond}\")\n    if fold not in (0, 1):\n        raise ValueError(f\"fold must be either 0 or 1, not {fold}\")\n    return hour, minute, second, microsecond, fold\n\ndef _check_tzinfo_arg(tz):\n    if tz is not None and not isinstance(tz, tzinfo):\n        raise TypeError(\n            \"tzinfo argument must be None or of a tzinfo subclass, \"\n            f\"not {type(tz).__name__!r}\"\n        )\n\ndef _divide_and_round(a, b):\n    \"\"\"divide a by b and round result to the nearest integer\n\n    When the ratio is exactly half-way between two integers,\n    the even integer is returned.","sourceCodeStart":573,"sourceCodeEnd":609,"githubUrl":"https://github.com/python/cpython/blob/bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6/Lib/_pydatetime.py#L573-L609","documentation":"Raised by _check_time_fields() when the second argument to time()/datetime() is not in 0..59. Notably, second=60 (a leap second) is invalid: CPython's datetime does not represent leap seconds, so UTC times like 23:59:60 must be handled before construction.","triggerScenarios":"time(23, 59, 60); parsing GPS/NTP or UTC timestamps during an inserted leap second; carrying 60 from sub-second rounding logic.","commonSituations":"Ingesting UTC time series or satellite/GPS data that contains :60 seconds; smearing or rounding bugs that produce second=60; test fixtures copied from leap-second tables.","solutions":["Convert leap seconds to second=59 with an extra-second flag, or smear, before constructing datetime","Use divmod carry: sec, rem = divmod(sec, 60) and add rem to minutes","Validate 0 <= second <= 59 in ingestion parsers"],"exampleFix":"// before\ndt = datetime(2016, 12, 31, 23, 59, 60)  # leap second -> ValueError\n// after\nif sec == 60:\n    dt = datetime(2016, 12, 31, 23, 59, 59)  # flag leap second separately\nelse:\n    dt = datetime(2016, 12, 31, 23, 59, sec)","handlingStrategy":"validation","validationCode":"if not 0 <= second <= 59:\n    raise ValueError('second must be 0..59 (leap seconds unsupported)')","typeGuard":"def valid_second(s) -> bool:\n    return 0 <= s <= 59","tryCatchPattern":null,"preventionTips":["Sanitize :60 leap seconds from GPS/NTP/UTC feeds before constructing datetimes","Round sub-second carries into minutes with divmod(sec, 60)"],"tags":["datetime","valueerror","validation","time","leap-second"],"backgroundTag":null,"analyzedSha":"bc6749cc3b5ae4a5e88a6cc2d5b3bebbe354eae6","analyzedAt":"2026-08-14T22:01:13.976Z","schemaVersion":2},"datasetVersion":"2026-08-15T17:31:12.345Z"}