diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractTemporalJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractTemporalJavaType.java index 1c1a12f79ebf..bda7ae012931 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractTemporalJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/AbstractTemporalJavaType.java @@ -4,6 +4,8 @@ */ package org.hibernate.type.descriptor.java; +import java.sql.Time; +import java.util.Calendar; import java.util.Comparator; import jakarta.persistence.TemporalType; @@ -60,6 +62,18 @@ private TemporalJavaType forMissingPrecision(TypeConfiguration typeConfig return (TemporalJavaType) this; } + public static Time millisToSqlTime(long millis) { + Calendar calendar = Calendar.getInstance(); + calendar.setTimeInMillis( millis ); + calendar.set(Calendar.YEAR, 1970); + calendar.set(Calendar.MONTH, 0); + calendar.set(Calendar.DAY_OF_MONTH, 1); + + final Time time = new Time(millis); + time.setTime( calendar.getTimeInMillis() ); + return time; + } + protected TemporalJavaType forTimestampPrecision(TypeConfiguration typeConfiguration) { throw new UnsupportedOperationException( this + " as `jakarta.persistence.TemporalType.TIMESTAMP` not supported" diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java index db5446e701ca..e81a5f7871f4 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarDateJavaType.java @@ -100,7 +100,7 @@ public X unwrap(Calendar value, Class type, WrapperOptions options) { return (X) new java.sql.Date( value.getTimeInMillis() ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( value.getTimeInMillis() % 86_400_000 ); + return (X) millisToSqlTime( value.getTimeInMillis() ); } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { return (X) new java.sql.Timestamp( value.getTimeInMillis() ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java index 3b23b21b162f..5a9b2e3eb604 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarJavaType.java @@ -117,7 +117,7 @@ public X unwrap(Calendar value, Class type, WrapperOptions options) { return (X) new java.sql.Date( value.getTimeInMillis() ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( value.getTimeInMillis() % 86_400_000 ); + return (X) millisToSqlTime( value.getTimeInMillis() ); } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { return (X) new java.sql.Timestamp( value.getTimeInMillis() ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java index 077c1fdb50c9..6c8d947a5fa8 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/CalendarTimeJavaType.java @@ -102,7 +102,7 @@ public X unwrap(Calendar value, Class type, WrapperOptions options) { return (X) new java.sql.Date( value.getTimeInMillis() ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( value.getTimeInMillis() % 86_400_000 ); + return (X) millisToSqlTime( value.getTimeInMillis() ); } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { return (X) new java.sql.Timestamp( value.getTimeInMillis() ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java index 1157578d10ce..241625152e57 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/DateJavaType.java @@ -124,7 +124,7 @@ public X unwrap(Date value, Class type, WrapperOptions options) { if ( java.sql.Time.class.isAssignableFrom( type ) ) { final java.sql.Time rtn = value instanceof java.sql.Time ? ( java.sql.Time ) value - : new java.sql.Time( value.getTime() % 86_400_000 ); + : millisToSqlTime( value.getTime() ); return (X) rtn; } if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java index 2bf123afbd54..6033fd5da694 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/InstantJavaType.java @@ -126,7 +126,7 @@ public X unwrap(Instant instant, Class type, WrapperOptions options) { } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) new java.sql.Time( instant.toEpochMilli() % 86_400_000 ); + return (X) millisToSqlTime( instant.toEpochMilli() ); } if ( Date.class.isAssignableFrom( type ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java index 58a990fec108..a86e12af8274 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcDateJavaType.java @@ -123,6 +123,14 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { return unwrapSqlDate( value ); } + if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { + return new java.sql.Timestamp( unwrapDateEpoch( value ) ); + } + + if ( java.sql.Time.class.isAssignableFrom( type ) ) { + throw new IllegalArgumentException( "Illegal attempt to treat `java.sql.Date` as `java.sql.Time`" ); + } + if ( java.util.Date.class.isAssignableFrom( type ) ) { return value; } @@ -141,14 +149,6 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { return cal; } - if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { - return new java.sql.Timestamp( unwrapDateEpoch( value ) ); - } - - if ( java.sql.Time.class.isAssignableFrom( type ) ) { - throw new IllegalArgumentException( "Illegal attempt to treat `java.sql.Date` as `java.sql.Time`" ); - } - throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java index 66dd05612700..23424875488b 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimeJavaType.java @@ -120,7 +120,7 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { if ( LocalTime.class.isAssignableFrom( type ) ) { final Time time = value instanceof java.sql.Time ? ( (java.sql.Time) value ) - : new java.sql.Time( value.getTime() % 86_400_000 ); + : millisToSqlTime( value.getTime() ); final LocalTime localTime = time.toLocalTime(); long millis = time.getTime() % 1000; if ( millis == 0 ) { @@ -135,9 +135,15 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { } if ( Time.class.isAssignableFrom( type ) ) { - return value instanceof Time - ? value - : new Time( value.getTime() % 86_400_000 ); + return millisToSqlTime( value.getTime() ); + } + + if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { + return new java.sql.Timestamp( value.getTime() ); + } + + if ( java.sql.Date.class.isAssignableFrom( type ) ) { + throw new IllegalArgumentException( "Illegal attempt to treat `java.sql.Time` as `java.sql.Date`" ); } if ( Date.class.isAssignableFrom( type ) ) { @@ -158,14 +164,6 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { return cal; } - if ( java.sql.Timestamp.class.isAssignableFrom( type ) ) { - return new java.sql.Timestamp( value.getTime() ); - } - - if ( java.sql.Date.class.isAssignableFrom( type ) ) { - throw new IllegalArgumentException( "Illegal attempt to treat `java.sql.Time` as `java.sql.Date`" ); - } - throw unknownUnwrap( type ); } @@ -175,12 +173,8 @@ public Date wrap(Object value, WrapperOptions options) { return null; } - if ( value instanceof Time time ) { - return time; - } - if ( value instanceof Date date ) { - return new Time( date.getTime() % 86_400_000 ); + return millisToSqlTime( date.getTime() ); } if ( value instanceof LocalTime localTime ) { @@ -197,7 +191,7 @@ public Date wrap(Object value, WrapperOptions options) { } if ( value instanceof Calendar calendar ) { - return new Time( calendar.getTimeInMillis() % 86_400_000 ); + return millisToSqlTime( calendar.getTimeInMillis() ); } throw unknownWrap( value.getClass() ); diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java index ade64a05d7fd..ec1aaa24a51c 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/JdbcTimestampJavaType.java @@ -127,6 +127,18 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { : new Timestamp( value.getTime() ); } + if ( java.sql.Date.class.isAssignableFrom( type ) ) { + return value instanceof java.sql.Date + ? ( java.sql.Date ) value + : new java.sql.Date( value.getTime() ); + } + + if ( java.sql.Time.class.isAssignableFrom( type ) ) { + return value instanceof java.sql.Time + ? ( java.sql.Time ) value + : millisToSqlTime( value.getTime() ); + } + if ( Date.class.isAssignableFrom( type ) ) { return value; } @@ -146,18 +158,6 @@ public Object unwrap(Date value, Class type, WrapperOptions options) { return value.getTime(); } - if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return value instanceof java.sql.Date - ? ( java.sql.Date ) value - : new java.sql.Date( value.getTime() ); - } - - if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return value instanceof java.sql.Time - ? ( java.sql.Time ) value - : new java.sql.Time( value.getTime() % 86_400_000 ); - } - throw unknownUnwrap( type ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java index 810ce18c9cad..1cacf5701556 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/LocalDateTimeJavaType.java @@ -97,12 +97,12 @@ public X unwrap(LocalDateTime value, Class type, WrapperOptions options) if ( java.sql.Date.class.isAssignableFrom( type ) ) { Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant(); - return (X) java.sql.Date.from( instant ); + return (X) new java.sql.Date( instant.toEpochMilli() ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant(); - return (X) java.sql.Time.from( instant ); + return (X) millisToSqlTime( instant.toEpochMilli() ); } if ( Date.class.isAssignableFrom( type ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java index cec90437010d..90525cba5f3f 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetDateTimeJavaType.java @@ -158,11 +158,11 @@ public X unwrap(OffsetDateTime offsetDateTime, Class type, WrapperOptions } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) java.sql.Date.from( offsetDateTime.toInstant() ); + return (X) new java.sql.Date( offsetDateTime.toInstant().toEpochMilli() ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) java.sql.Time.from( offsetDateTime.toInstant() ); + return (X) millisToSqlTime( offsetDateTime.toInstant().toEpochMilli() ); } if ( Date.class.isAssignableFrom( type ) ) { diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java index 1fc1d7939316..da9f2f70e813 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaType.java @@ -138,6 +138,10 @@ public X unwrap(OffsetTime offsetTime, Class type, WrapperOptions options return (X) Long.valueOf( instant.toEpochMilli() ); } + if ( java.sql.Date.class.isAssignableFrom( type ) ) { + throw new IllegalArgumentException( "Illegal attempt to treat `java.time.OffsetTime` as `java.sql.Date`" ); + } + if ( Date.class.isAssignableFrom( type ) ) { return (X) Date.from( instant ); } diff --git a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java index d17661d6132c..fd9e1fb3b7b0 100644 --- a/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java +++ b/hibernate-core/src/main/java/org/hibernate/type/descriptor/java/ZonedDateTimeJavaType.java @@ -120,11 +120,11 @@ public X unwrap(ZonedDateTime zonedDateTime, Class type, WrapperOptions o } if ( java.sql.Date.class.isAssignableFrom( type ) ) { - return (X) java.sql.Date.from( zonedDateTime.toInstant() ); + return (X) new java.sql.Date( zonedDateTime.toInstant().toEpochMilli() ); } if ( java.sql.Time.class.isAssignableFrom( type ) ) { - return (X) java.sql.Time.from( zonedDateTime.toInstant() ); + return (X) millisToSqlTime( zonedDateTime.toInstant().toEpochMilli() ); } if ( Date.class.isAssignableFrom( type ) ) { diff --git a/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/type/java/DateSubclassesUnwrapTest.java b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/type/java/DateSubclassesUnwrapTest.java new file mode 100644 index 000000000000..dc17ccc4bf1f --- /dev/null +++ b/hibernate-core/src/test/java/org/hibernate/orm/test/mapping/type/java/DateSubclassesUnwrapTest.java @@ -0,0 +1,219 @@ +/* + * SPDX-License-Identifier: Apache-2.0 + * Copyright Red Hat Inc. and Hibernate Authors + */ +package org.hibernate.orm.test.mapping.type.java; + +import java.sql.Time; +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.OffsetDateTime; +import java.time.OffsetTime; +import java.time.ZonedDateTime; +import java.util.Calendar; +import java.util.Date; + +import org.hibernate.HibernateException; +import org.hibernate.type.descriptor.WrapperOptions; +import org.hibernate.type.descriptor.java.CalendarDateJavaType; +import org.hibernate.type.descriptor.java.CalendarJavaType; +import org.hibernate.type.descriptor.java.CalendarTimeJavaType; +import org.hibernate.type.descriptor.java.DateJavaType; +import org.hibernate.type.descriptor.java.InstantJavaType; +import org.hibernate.type.descriptor.java.JdbcDateJavaType; +import org.hibernate.type.descriptor.java.JdbcTimeJavaType; +import org.hibernate.type.descriptor.java.JdbcTimestampJavaType; +import org.hibernate.type.descriptor.java.LocalDateJavaType; +import org.hibernate.type.descriptor.java.LocalDateTimeJavaType; +import org.hibernate.type.descriptor.java.LocalTimeJavaType; +import org.hibernate.type.descriptor.java.OffsetDateTimeJavaType; +import org.hibernate.type.descriptor.java.OffsetTimeJavaType; +import org.hibernate.type.descriptor.java.ZonedDateTimeJavaType; + +import org.hibernate.testing.orm.junit.DomainModel; +import org.hibernate.testing.orm.junit.SessionFactory; +import org.hibernate.testing.orm.junit.SessionFactoryScope; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.junit.jupiter.api.Assertions.assertThrows; + +@DomainModel +@SessionFactory +public class DateSubclassesUnwrapTest { + @Test + void testJdbcTimestampJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final JdbcTimestampJavaType javaType = JdbcTimestampJavaType.INSTANCE; + final Date date = new Date(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( date, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( date, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( date, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( date, Date.class, wrapperOptions ) ); + } + + @Test + void testJdbcDateJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final JdbcDateJavaType javaType = JdbcDateJavaType.INSTANCE; + final Date date = new Date(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( date, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( date, java.sql.Date.class, wrapperOptions ) ); + assertThrows( IllegalArgumentException.class, () -> javaType.unwrap( date, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( date, Date.class, wrapperOptions ) ); + } + + @Test + void testJdbcTimeJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final JdbcTimeJavaType javaType = JdbcTimeJavaType.INSTANCE; + final Date date = new Date(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( date, Timestamp.class, wrapperOptions ) ); + Assertions.assertThrows( + IllegalArgumentException.class, + () -> javaType.unwrap( date, java.sql.Date.class, wrapperOptions ) + ); + assertInstanceOf( Time.class, javaType.unwrap( date, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( date, Date.class, wrapperOptions ) ); + } + + @Test + void testDateJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final DateJavaType javaType = DateJavaType.INSTANCE; + final Date date = new Date(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( date, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( date, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( date, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( date, Date.class, wrapperOptions ) ); + } + + @Test + void testInstantJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final InstantJavaType javaType = InstantJavaType.INSTANCE; + final Instant instant = Instant.now(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( instant, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( instant, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( instant, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( instant, Date.class, wrapperOptions ) ); + } + + @Test + void testLocalDateJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final LocalDateJavaType javaType = LocalDateJavaType.INSTANCE; + final LocalDate date = LocalDate.now(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( date, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( date, java.sql.Date.class, wrapperOptions ) ); + assertThrows( HibernateException.class, () -> javaType.unwrap( date, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( date, Date.class, wrapperOptions ) ); + } + + @Test + void testLocalDateTimeJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final LocalDateTimeJavaType javaType = LocalDateTimeJavaType.INSTANCE; + final LocalDateTime dateTime = LocalDateTime.now(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( dateTime, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( dateTime, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( dateTime, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( dateTime, Date.class, wrapperOptions ) ); + } + + @Test + void testLocalTimeJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final LocalTimeJavaType javaType = LocalTimeJavaType.INSTANCE; + final LocalTime time = LocalTime.now(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( time, Timestamp.class, wrapperOptions ) ); + assertThrows( HibernateException.class, () -> javaType.unwrap( time, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( time, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( time, Date.class, wrapperOptions ) ); + } + + @Test + void testOffsetDateTimeJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final OffsetDateTimeJavaType javaType = OffsetDateTimeJavaType.INSTANCE; + final OffsetDateTime dateTime = OffsetDateTime.now(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( dateTime, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( dateTime, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( dateTime, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( dateTime, Date.class, wrapperOptions ) ); + } + + @Test + void testOffsetTimeJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final OffsetTimeJavaType javaType = OffsetTimeJavaType.INSTANCE; + final OffsetTime time = OffsetTime.now(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( time, Timestamp.class, wrapperOptions ) ); + assertThrows( IllegalArgumentException.class, + () -> javaType.unwrap( time, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( time, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( time, Date.class, wrapperOptions ) ); + } + + @Test + void testZonedDateTimeJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final ZonedDateTimeJavaType javaType = ZonedDateTimeJavaType.INSTANCE; + final ZonedDateTime dateTime = ZonedDateTime.now(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( dateTime, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( dateTime, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( dateTime, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( dateTime, Date.class, wrapperOptions ) ); + } + + @Test + void testCalendarDateJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final CalendarDateJavaType javaType = CalendarDateJavaType.INSTANCE; + final Calendar calendar = Calendar.getInstance(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( calendar, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( calendar, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( calendar, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( calendar, Date.class, wrapperOptions ) ); + } + + @Test + void testCalendarJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final CalendarJavaType javaType = CalendarJavaType.INSTANCE; + final Calendar calendar = Calendar.getInstance(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( calendar, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( calendar, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( calendar, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( calendar, Date.class, wrapperOptions ) ); + } + + @Test + void testCalendarTimeJavaType(SessionFactoryScope scope) { + final WrapperOptions wrapperOptions = scope.getSessionFactory().getWrapperOptions(); + final CalendarTimeJavaType javaType = CalendarTimeJavaType.INSTANCE; + final Calendar calendar = Calendar.getInstance(); + + assertInstanceOf( Timestamp.class, javaType.unwrap( calendar, Timestamp.class, wrapperOptions ) ); + assertInstanceOf( java.sql.Date.class, javaType.unwrap( calendar, java.sql.Date.class, wrapperOptions ) ); + assertInstanceOf( Time.class, javaType.unwrap( calendar, Time.class, wrapperOptions ) ); + assertInstanceOf( Date.class, javaType.unwrap( calendar, Date.class, wrapperOptions ) ); + } +}