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
72 lines
4.6 KiB
Markdown
72 lines
4.6 KiB
Markdown
# 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`](../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
|
|
|
|
```bash
|
|
./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.
|