{"record":{"id":"4a0c2260586b9fd9","repo":"angular/components","slug":"invalid-hours-hours-hours-value-must-be-betw-4a0c22","errorCode":null,"errorMessage":"Invalid hours \"${hours}\". Hours value must be between 0 and 23.","messagePattern":"Invalid hours \"(.+?)\"\\. Hours value must be between 0 and 23\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"src/material/core/datetime/native-date-adapter.ts","lineNumber":247,"sourceCode":"    return super.deserialize(value);\n  }\n\n  isDateInstance(obj: any) {\n    return obj instanceof Date;\n  }\n\n  isValid(date: Date) {\n    return !isNaN(date.getTime());\n  }\n\n  invalid(): Date {\n    return new Date(NaN);\n  }\n\n  override setTime(target: Date, hours: number, minutes: number, seconds: number): Date {\n    if (typeof ngDevMode === 'undefined' || ngDevMode) {\n      if (!inRange(hours, 0, 23)) {\n        throw Error(`Invalid hours \"${hours}\". Hours value must be between 0 and 23.`);\n      }\n\n      if (!inRange(minutes, 0, 59)) {\n        throw Error(`Invalid minutes \"${minutes}\". Minutes value must be between 0 and 59.`);\n      }\n\n      if (!inRange(seconds, 0, 59)) {\n        throw Error(`Invalid seconds \"${seconds}\". Seconds value must be between 0 and 59.`);\n      }\n    }\n\n    const clone = this.clone(target);\n    clone.setHours(hours, minutes, seconds, 0);\n    return clone;\n  }\n\n  override getHours(date: Date): number {\n    return date.getHours();","sourceCodeStart":229,"sourceCodeEnd":265,"githubUrl":"https://github.com/angular/components/blob/0411926e7d8ae06b32236ec1048a888cfad5abf2/src/material/core/datetime/native-date-adapter.ts#L229-L265","documentation":"NativeDateAdapter.setTime sets the time-of-day on a cloned Date and validates each component in dev mode. Hours outside 0-23 would roll over into the next/previous day via Date's overflow behavior, so out-of-range values are rejected.","triggerScenarios":"Calling adapter.setTime(target, hours, minutes, seconds) with hours not in [0,23] — e.g. 12-hour-clock values like 24 for midnight, or unvalidated user/parsed input (often via _parseTimeString paths).","commonSituations":"Converting '12:00 AM' to 24 and passing it through; spreadsheet/CSV time columns with values like 24:00; modular arithmetic errors when adding durations to hours.","solutions":["Convert 12-hour input correctly: 12 AM -> 0, 12 PM -> 12, before calling setTime.","Validate inRange(hours, 0, 23) on inputs before calling.","Use adapter.addCalendarHours to add durations instead of mutating hour arithmetic."],"exampleFix":"// before\nadapter.setTime(target, 24, 0, 0); // meant midnight\n// after\nadapter.setTime(target, 0, 0, 0);","handlingStrategy":"validation","validationCode":"if (!Number.isInteger(hours) || hours < 0 || hours > 23) {\n  throw new RangeError(`hours must be 0-23, got ${hours}`);\n}\nadapter.setTime(target, hours, minutes, seconds);","typeGuard":"function isValidHours(h: unknown): h is number {\n  return typeof h === 'number' && Number.isInteger(h) && h >= 0 && h <= 23;\n}","tryCatchPattern":"try {\n  adapter.setTime(target, hours, m, s);\n} catch (e) {\n  if (e instanceof Error && e.message.includes('Invalid hours')) {\n    logger.warn(`hour ${hours} out of range, clamping`);\n    adapter.setTime(target, ((hours % 24) + 24) % 24, m, s);\n  } else { throw e; }\n}","preventionTips":["Convert 12-hour times correctly (12 AM -> 0, 12 PM -> 12).","Reject or normalize '24:00' style inputs at the form layer.","Use adapter.addCalendarHours for hour arithmetic."],"tags":["angular-material","date-adapter","time-validation","hours"],"backgroundTag":"invalid-time-value","analyzedSha":"0411926e7d8ae06b32236ec1048a888cfad5abf2","analyzedAt":"2026-08-31T11:58:23.400Z","schemaVersion":2},"datasetVersion":"2026-09-01T08:17:40.651Z"}