Hibernate 7.4.14.Final (plus an 8.0.0.Beta4 preview run), H2 2.5.252, PostgreSQL 17.11 in Docker. Same-JVM and cross-zone round trips, @TimeZoneStorage modes, DST gap/overlap, precision (precision vs secondPrecision), hibernate.jdbc.time_zone, java_time_use_direct_jdbc default flip. Supersedes the date/time experiments of docs/13 (7.4.5); chapter 13 is unchanged. Co-Authored-By: Claude Sonnet 5.5 <[email protected]> Claude-Session: https://claude.ai/code/session_017ic4b7rnC7jppGGdHGESvy
4.6 KiB
date-time
Companion module for the ankurm.com article Hibernate 7 Date and Time Mapping: Instant vs LocalDateTime vs
OffsetDateTime (What Round-Trips). Plain Hibernate (no Spring). One moment is written into every java.time
column, then read back in a new session, in a JVM with a different default time zone, on two databases.
Each test writes what it observed to output/ and asserts the same facts.
This module supersedes the date/time experiments in the main project's
docs/13-date-and-time-mapping.md (Hibernate 7.4.5, H2 and HSQLDB only,
every run inside one JVM zone). Chapter 13 is left as it was; where this module disagrees with it, this module is newer.
Versions
| Component | Version | Notes |
|---|---|---|
| Hibernate ORM | 7.4.14.Final |
latest 7.x GA on Maven Central on 2026-10-28 |
| Hibernate ORM (preview run) | 8.0.0.Beta4 |
pre-release, published 2026-10-28; -Dhibernate.version=8.0.0.Beta4 -Dpersistence.version=4.0.0-M7 -Dh.label=h8 |
| Jakarta Persistence | 3.2.0 (4.0.0-M7 for the Hibernate 8 run) |
|
| H2 | 2.5.252 |
file database, so a second JVM can read what the first wrote |
| PostgreSQL | 17.11 (postgres:17-alpine in Docker), driver org.postgresql:postgresql:42.7.14 |
server TimeZone is UTC; see output/00-environment.txt |
| HSQLDB | 2.7.4 |
only the precision comparison |
| JUnit Jupiter / AssertJ | 6.0.3 / 3.27.7 |
|
| Java | 25 (Temurin 25.0.5+8) |
Run
./scripts/run-all.sh # whole matrix; needs Docker for PostgreSQL. H7_ONLY=1 skips the Hibernate 8 beta runs
mvn test # H2 only, in your JVM's own time zone
mvn test -Ddt.jvmargs=-Duser.timezone=America/New_York
run-all.sh runs the suite for each database in JVM zones Asia/Kolkata (+05:30, no DST) and
America/New_York (DST), then a cross-zone pass (write in one JVM zone, read in a JVM with the other), then
hibernate.type.java_time_use_direct_jdbc=true on Hibernate 7, then the Hibernate 8 beta with its default and with
the flag set back to false.
Output
File names are NN-topic-<db>-<JVM zone>[-variant][-directtrue|-directfalse]-<h7|h8>.txt. The header of every file states the
Hibernate version, database version, JVM zone and the effective java_time_use_direct_jdbc. directtrue / directfalse
mean the flag was set explicitly; no suffix means that Hibernate line's default (false on 7.4, true on 8.0.0.Beta4).
| Prefix | What it shows |
|---|---|
00-environment |
JDK, PostgreSQL server and image digest, drivers |
01-roundtrip |
one moment in Instant, LocalDateTime, OffsetDateTime (default, NATIVE, NORMALIZE, NORMALIZE_UTC, COLUMN): in, out, equal?, same instant?, raw column text. same-jvm or written-in-<zone> (cross-zone) |
02-dst |
a LocalDateTime inside New York's spring-forward gap and one inside the fall-back overlap |
03-precision |
nanoseconds written, what comes back (H2, PostgreSQL, HSQLDB) |
04-zoned / 04-zoned-failure |
ZonedDateTime round trip; the PostgreSQL + direct JDBC bind and read failure on Hibernate 7.4 |
05-ddl |
column types Hibernate generated, from information_schema |
06-jdbc-time-zone |
hibernate.jdbc.time_zone set to the zone the JVM is not in |
07-preferred-instant-jdbc-type |
TIMESTAMP vs TIMESTAMP_UTC for Instant |
08-column-precision |
@Column(precision) vs @Column(secondPrecision) |
09-legacy-types |
java.util.Date without @Temporal, Year, YearMonth, Duration |
10-javap-* |
enum constants, setting names and @Temporal deprecation read from the jars |
Sources
| File | Role |
|---|---|
src/main/java/com/ankurm/datetime/Event.java |
the entity with one column per mapping |
src/main/java/com/ankurm/datetime/ZonedEvent.java |
ZonedDateTime on its own entity (it cannot be bound on one driver setting) |
src/main/java/com/ankurm/datetime/Probe.java, PrecisionEvent.java, Legacy.java |
narrow entities for the edge cases |
src/main/java/com/ankurm/datetime/Db.java |
builds the SessionFactory for H2 / PostgreSQL / HSQLDB from system properties |
src/test/java/com/ankurm/datetime/RoundTripTest.java |
the round trip, same-JVM and cross-zone |
src/test/java/com/ankurm/datetime/EdgeCasesTest.java |
DST gap and overlap, precision, generated DDL |
src/test/java/com/ankurm/datetime/ZonedTest.java, JdbcTimeZoneTest.java, TypesTest.java |
the rest |
This module has its own pom.xml and does not use the Spring Boot parent of the main hibernate-demo project. The
Hibernate 8 results are from a beta and can change before 8.0 final.