{"record":{"id":"52800dacb3d5a666","repo":"hibernate/hibernate-orm","slug":"could-not-parse-timestamp-string-s-52800d","errorCode":null,"errorMessage":"could not parse timestamp string %s","messagePattern":"could not parse timestamp string (.+?)","errorType":"exception","errorClass":"HibernateException","httpStatus":null,"severity":"error","filePath":"hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java","lineNumber":118,"sourceCode":"\t}\n\n\t@Override\n\tpublic OffsetDateTime fromString(CharSequence string) {\n\t\treturn OffsetDateTime.from( ISO_OFFSET_DATE_TIME.parse( string ) );\n\t}\n\n\t@Override\n\tpublic OffsetDateTime fromEncodedString(CharSequence charSequence, int start, int end) {\n\t\ttry {\n\t\t\tfinal var temporalAccessor = PARSE_FORMATTER.parse( subSequence( charSequence, start, end ) );\n\t\t\treturn temporalAccessor.isSupported( ChronoField.OFFSET_SECONDS )\n\t\t\t\t\t? OffsetDateTime.from( temporalAccessor )\n\t\t\t\t\t// For databases that don't have timezone support,\n\t\t\t\t\t// we encode timestamps at UTC, so allow parsing\n\t\t\t\t\t: LocalDateTime.from( temporalAccessor ).atOffset( ZoneOffset.UTC );\n\t\t}\n\t\tcatch ( DateTimeParseException pe) {\n\t\t\tthrow new HibernateException( \"could not parse timestamp string \"\n\t\t\t\t\t\t+ subSequence( charSequence, start, end ), pe );\n\t\t}\n\t}\n\n\t@Override\n\tpublic <X> X unwrap(OffsetDateTime offsetDateTime, Class<X> type, WrapperOptions options) {\n\t\tif ( offsetDateTime == null ) {\n\t\t\treturn null;\n\t\t}\n\n\t\tif ( OffsetDateTime.class.isAssignableFrom( type ) ) {\n\t\t\treturn type.cast( offsetDateTime );\n\t\t}\n\n\t\tif ( ZonedDateTime.class.isAssignableFrom( type ) ) {\n\t\t\treturn type.cast( offsetDateTime.toZonedDateTime() );\n\t\t}\n","sourceCodeStart":100,"sourceCodeEnd":136,"githubUrl":"https://github.com/hibernate/hibernate-orm/blob/fad1729dce015f908198d57a8d80274a30f905a5/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java#L100-L136","documentation":"OffsetDateTimeJavaType.fromEncodedString() parses the text Hibernate stored for OffsetDateTime on databases without full timezone support. PARSE_FORMATTER accepts ISO_LOCAL_DATE_TIME with an optional offset ('+HH:MM:ss' or 'Z'); if no offset is present the value is assumed UTC. Text with a space separator, compact offsets like '+0100', trailing characters, or a bare date fails DateTimeParseException and is rethrown as HibernateException(\"could not parse timestamp string ...\").","triggerScenarios":"Dialect without native timezone support stores OffsetDateTime as text and the column content is not ISO-8601 (space separator, 'Z' variants like 'UTC'); changing hibernate.timezone.default_storage (e.g. NORMAL vs NORMALIZE_UTC) after data was written so the read format no longer matches; rows imported from CSV with re-formatted timestamps","commonSituations":"Migrating between databases with different timestamptz handling; storage-strategy configuration changes without data rewrite; hand-edited or externally loaded timestamp text","solutions":["Re-encode the stored text to ISO local date-time with optional numeric offset ('2024-12-31T10:15:30' or '...+01:00')","Prefer a native TIMESTAMP_WITH_TIMEZONE column and TimeZoneStorageType.NATIVE where the dialect supports it","Keep hibernate.timezone.default_storage identical between the code that wrote and reads the data; rewrite data when it changes","Add an AttributeConverter for the affected attribute that parses the actual legacy format"],"exampleFix":"// before: encoded column holds '2024-12-31 10:15:30 +01:00'\n// load -> HibernateException: could not parse timestamp string ...\n\n// after\nUPDATE meetings SET ts_text = REPLACE(ts_text, ' ', 'T');\n-- '2024-12-31T10:15:30+01:00' parses (space only between date/time removed; offset kept compact fails -> use +01:00 form)","handlingStrategy":"validation","validationCode":"static final java.time.format.DateTimeFormatter F = new java.time.format.DateTimeFormatterBuilder()\n    .append(java.time.format.DateTimeFormatter.ISO_LOCAL_DATE_TIME)\n    .optionalStart().appendOffset(\"+HH:MM:ss\", \"Z\").optionalEnd().toFormatter();\n\nstatic boolean isParsableOffsetDateTimeText(CharSequence s) {\n    try { F.parse(s); return true; } catch (java.time.format.DateTimeParseException e) { return false; }\n}","typeGuard":"static java.time.OffsetDateTime tryOffsetDateTime(String s) {\n    try { return java.time.OffsetDateTime.parse(s); } catch (Exception e) { return null; }\n}","tryCatchPattern":"catch (HibernateException e) {\n    if (e.getCause() instanceof DateTimeParseException)\n        throw new IllegalArgumentException(\"Stored timestamp text is not ISO date-time[offset]: '\" + text + \"'\", e);\n    throw e;\n}","preventionTips":["Pin hibernate.timezone.default_storage at project start and never change it without a data migration","Prefer native timestamptz columns (TimeZoneStorageType.NATIVE)","Validate stored text in bulk after imports or storage-strategy changes"],"tags":["hibernate","offsetdatetime","timestamp-parsing","timezone-storage","encoded-string"],"backgroundTag":"datetime-string-parse-error","analyzedSha":"fad1729dce015f908198d57a8d80274a30f905a5","analyzedAt":"2026-08-22T04:13:57.527Z","schemaVersion":2},"datasetVersion":"2026-08-22T09:17:25.309Z"}