{"record":{"id":"8d873a4cc64695a2","repo":"hibernate/hibernate-orm","slug":"could-not-parse-time-string-s-8d873a","errorCode":null,"errorMessage":"could not parse time string %s","messagePattern":"could not parse time string (.+?)","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java","lineNumber":259,"sourceCode":"\t\t\t\t: LocalTime.ofInstant( value.toInstant(), ZoneOffset.systemDefault() );\n\t}\n\n\t@Override\n\tpublic String toString(Time value) {\n\t\treturn LITERAL_FORMATTER.format( fromDate( value ) );\n\t}\n\n\t@Override\n\tpublic Time fromString(CharSequence string) {\n\t\ttry {\n\t\t\tfinal var temporalAccessor = LITERAL_FORMATTER.parse( string );\n\t\t\tfinal var localTime = LocalTime.from( temporalAccessor );\n\t\t\tfinal var time = Time.valueOf( localTime );\n\t\t\ttime.setTime( time.getTime() + localTime.getNano() / 1_000_000 );\n\t\t\treturn time;\n\t\t}\n\t\tcatch ( DateTimeParseException pe) {\n\t\t\tthrow new HibernateException( \"could not parse time string \" + string, pe );\n\t\t}\n\t}\n\n\t@Override\n\tpublic Time fromEncodedString(CharSequence charSequence, int start, int end) {\n\t\ttry {\n\t\t\tfinal var temporalAccessor = ENCODED_FORMATTER.parse( subSequence( charSequence, start, end ) );\n\t\t\treturn Time.valueOf( temporalAccessor.query( LocalTime::from ) );\n\t\t}\n\t\tcatch ( DateTimeParseException pe) {\n\t\t\tthrow new HibernateException( \"could not parse time string \" + subSequence( charSequence, start, end ), pe );\n\t\t}\n\t}\n\n\t@Override\n\tpublic void appendEncodedString(SqlAppender sb, Time value) {\n\t\tLITERAL_FORMATTER.formatTo( fromDate( value ), sb );\n\t}","sourceCodeStart":241,"sourceCodeEnd":277,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java#L241-L277","documentation":"JdbcTimeJavaType.fromString() parses time text with DateTimeFormatter.ISO_LOCAL_TIME, which requires 24-hour HH:mm:ss (fractional seconds allowed). Any other shape - 12-hour clock with AM/PM, missing seconds, trailing spaces, empty string - throws DateTimeParseException, rethrown as HibernateException(\"could not parse time string ...\"). This path is used for HQL time literals and string-to-Time conversion.","triggerScenarios":"HQL literal like ... where e.start = '3:04 PM' or '10:15' (only '15:04:05' or '15:04:05.123' parse); fromString called with data exported from UI time pickers using 12-hour format; a String value coerced into a java.sql.Time attribute.","commonSituations":"Front-end time pickers producing 'h:mm a' strings; CSV/Excel imports with times like '3:04:05 PM'; locale-formatted time strings bound as literals in JPQL.","solutions":["Convert times to 24-hour HH:mm:ss before binding or storing","Use typed parameters (LocalTime or java.sql.Time) instead of string literals in queries","Add an AttributeConverter that parses the legacy 12-hour format with a matching formatter","Trim inputs and validate with LocalTime.parse before persisting"],"exampleFix":"// before\nem.createQuery(\"select s from Shift s where s.begin = '3:04 PM'\") // HibernateException\n\n// after\nem.createQuery(\"select s from Shift s where s.begin = '15:04:05'\")\n// or: query.setParameter(\"begin\", LocalTime.of(15,4,5));","handlingStrategy":"validation","validationCode":"static boolean isIsoTime(CharSequence s) {\n    try { java.time.LocalTime.parse(s); return true; }\n    catch (java.time.format.DateTimeParseException e) { return false; }\n}\n\nif (!isIsoTime(text.trim())) throw new IllegalArgumentException(\"Expected HH:mm:ss: \" + text);","typeGuard":"static java.time.LocalTime tryIsoTime(String s) {\n    try { return java.time.LocalTime.parse(s.trim()); } catch (Exception e) { return null; }\n}","tryCatchPattern":"try { Time t = JdbcTimeJavaType.INSTANCE.fromString(text); }\ncatch (HibernateException e) {\n    if (e.getCause() instanceof DateTimeParseException)\n        throw new IllegalArgumentException(\"Bad time text: '\" + text + \"' (expected HH:mm:ss)\", e);\n    throw e;\n}","preventionTips":["Convert 12-hour picker output to 24-hour HH:mm:ss at the UI boundary","Bind LocalTime/java.sql.Time parameters, not strings","Trim and validate time strings in DTO validation before they reach persistence"],"tags":["hibernate","time-parsing","iso-local-time","hql-literal","datetimeformatter"],"backgroundTag":"datetime-string-parse-error","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}