HHH-18532 Suggested fix to conversion of epoch time in milliseconds to java.sql.Time

This commit is contained in:
Čedomir Igaly 2024-09-19 11:10:11 +02:00
parent 871c203777
commit 7b560a8bbd
13 changed files with 31 additions and 32 deletions

View File

@ -4,6 +4,10 @@
*/
package org.hibernate.type.descriptor.java;
import java.sql.Time;
import java.time.Instant;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.Comparator;
import jakarta.persistence.TemporalType;
@ -60,6 +64,13 @@ public abstract class AbstractTemporalJavaType<T>
return (TemporalJavaType) this;
}
public static Time millisToSqlTime(long millis) {
final LocalTime localTime = Instant.ofEpochMilli( millis ).atZone( ZoneId.systemDefault() ).toLocalTime();
final Time time = Time.valueOf( localTime );
time.setTime( time.getTime() + localTime.getNano() / 1_000_000 );
return time;
}
protected <X> TemporalJavaType<X> forTimestampPrecision(TypeConfiguration typeConfiguration) {
throw new UnsupportedOperationException(
this + " as `jakarta.persistence.TemporalType.TIMESTAMP` not supported"

View File

@ -100,7 +100,7 @@ public class CalendarDateJavaType extends AbstractTemporalJavaType<Calendar> {
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() );

View File

@ -117,7 +117,7 @@ public class CalendarJavaType extends AbstractTemporalJavaType<Calendar> impleme
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() );

View File

@ -102,7 +102,7 @@ public class CalendarTimeJavaType extends AbstractTemporalJavaType<Calendar> {
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() );

View File

@ -124,7 +124,7 @@ public class DateJavaType extends AbstractTemporalJavaType<Date> implements Vers
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 ) ) {

View File

@ -126,7 +126,7 @@ public class InstantJavaType extends AbstractTemporalJavaType<Instant>
}
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 ) ) {

View File

@ -120,7 +120,7 @@ public class JdbcTimeJavaType extends AbstractTemporalJavaType<Date> {
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,7 @@ public class JdbcTimeJavaType extends AbstractTemporalJavaType<Date> {
}
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 ) ) {
@ -175,12 +173,8 @@ public class JdbcTimeJavaType extends AbstractTemporalJavaType<Date> {
return null;
}
if ( value instanceof Time ) {
return (Date) value;
}
if ( value instanceof Date ) {
return new Time( ( (Date) value ).getTime() % 86_400_000 );
return millisToSqlTime( ( (Date) value ).getTime() );
}
if ( value instanceof LocalTime ) {
@ -198,7 +192,7 @@ public class JdbcTimeJavaType extends AbstractTemporalJavaType<Date> {
}
if ( value instanceof Calendar ) {
return new Time( ( (Calendar) value ).getTimeInMillis() % 86_400_000 );
return millisToSqlTime( ( (Calendar) value ).getTimeInMillis() );
}
throw unknownWrap( value.getClass() );

View File

@ -137,7 +137,7 @@ public class JdbcTimestampJavaType extends AbstractTemporalJavaType<Date> implem
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 );
: millisToSqlTime( value.getTime() );
}
if ( Date.class.isAssignableFrom( type ) ) {

View File

@ -102,7 +102,7 @@ public class LocalDateTimeJavaType extends AbstractTemporalJavaType<LocalDateTim
if ( java.sql.Time.class.isAssignableFrom( type ) ) {
Instant instant = value.atZone( ZoneId.systemDefault() ).toInstant();
return (X) new java.sql.Time( instant.toEpochMilli() % 86_400_000 );
return (X) millisToSqlTime( instant.toEpochMilli() );
}
if ( Date.class.isAssignableFrom( type ) ) {

View File

@ -157,7 +157,7 @@ public class OffsetDateTimeJavaType extends AbstractTemporalJavaType<OffsetDateT
}
if ( java.sql.Time.class.isAssignableFrom( type ) ) {
return (X) new java.sql.Time( offsetDateTime.toInstant().toEpochMilli() % 86_400_000 );
return (X) millisToSqlTime( offsetDateTime.toInstant().toEpochMilli() );
}
if ( Date.class.isAssignableFrom( type ) ) {

View File

@ -124,7 +124,7 @@ public class ZonedDateTimeJavaType extends AbstractTemporalJavaType<ZonedDateTim
}
if ( java.sql.Time.class.isAssignableFrom( type ) ) {
return (X) new java.sql.Time( zonedDateTime.toInstant().toEpochMilli() % 86_400_000 );
return (X) millisToSqlTime( zonedDateTime.toInstant().toEpochMilli() );
}
if ( Date.class.isAssignableFrom( type ) ) {

View File

@ -1,8 +1,6 @@
/*
* Hibernate, Relational Persistence for Idiomatic Java
*
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.mapping.type.java;
@ -17,15 +15,8 @@ import java.time.OffsetTime;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
import org.hibernate.HibernateException;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.engine.jdbc.LobCreator;
import org.hibernate.engine.jdbc.NonContextualLobCreator;
import org.hibernate.engine.spi.SessionFactoryImplementor;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.CalendarDateJavaType;
import org.hibernate.type.descriptor.java.CalendarJavaType;
@ -173,7 +164,7 @@ public class DateSubclassesUnwrapTest {
assertInstanceOf( Timestamp.class, javaType.unwrap( time, Timestamp.class, wrapperOptions ) );
assertThrows( IllegalArgumentException.class,
() -> javaType.unwrap( time, java.sql.Date.class, wrapperOptions ) );
() -> 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 ) );
}

View File

@ -1,3 +1,7 @@
/*
* SPDX-License-Identifier: LGPL-2.1-or-later
* Copyright Red Hat Inc. and Hibernate Authors
*/
package org.hibernate.orm.test.mapping.type.java;
import java.sql.Time;
@ -43,7 +47,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
@DomainModel(annotatedClasses = GoodBadUglyTest.Times.class)
@SessionFactory
@SkipForDialect(dialectClass = InformixDialect.class)
@Disabled
public class GoodBadUglyTest {
@BeforeEach