Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.time.OffsetTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.util.Calendar;
import java.util.Date;
Expand Down Expand Up @@ -65,6 +65,12 @@ public <X> X unwrap(OffsetTime offsetTime, Class<X> type, WrapperOptions options
final ZonedDateTime zonedDateTime = offsetTime.atDate( LocalDate.of( 1970, 1, 1 ) ).toZonedDateTime();

if ( Timestamp.class.isAssignableFrom( type ) ) {
/*
* Workaround for HHH-13266 (JDK-8061577).
* Ideally we'd want to use Timestamp.from( offsetDateTime.toInstant() ), but this won't always work.
* Timestamp.from() assumes the number of milliseconds since the epoch
* means the same thing in Timestamp and Instant, but it doesn't, in particular before 1900.
*/
return (X) Timestamp.valueOf( zonedDateTime.toLocalDateTime() );
}

Expand Down Expand Up @@ -95,22 +101,44 @@ public <X> OffsetTime wrap(X value, WrapperOptions options) {
return (OffsetTime) value;
}

/*
* Also, in order to fix HHH-13357, and to be consistent with the conversion to Time (see above),
* we set the offset to the current offset of the JVM (OffsetDateTime.now().getOffset()).
* This is different from setting the *zone* to the current *zone* of the JVM (ZoneId.systemDefault()),
* since a zone has a varying offset over time,
* thus the zone might have a different offset for the given timezone than it has for the current date/time.
* For example, if the timestamp represents 1970-01-01TXX:YY,
* and the JVM is set to use Europe/Paris as a timezone, and the current time is 2019-04-16-08:53,
* then applying the JVM timezone to the timestamp would result in the offset +01:00,
* but applying the JVM offset would result in the offset +02:00, since DST is in effect at 2019-04-16-08:53.
*
* Of course none of this would be a problem if we just stored the offset in the database,
* but I guess there are historical reasons that explain why we don't.
*/
ZoneOffset offset = OffsetDateTime.now().getOffset();

if ( Time.class.isInstance( value ) ) {
return ( (Time) value ).toLocalTime().atOffset( OffsetDateTime.now().getOffset() );
return ( (Time) value ).toLocalTime().atOffset( offset );
}

if ( Timestamp.class.isInstance( value ) ) {
final Timestamp ts = (Timestamp) value;
return OffsetTime.ofInstant( ts.toInstant(), ZoneId.systemDefault() );
/*
* Workaround for HHH-13266 (JDK-8061577).
* Ideally we'd want to use OffsetDateTime.ofInstant( ts.toInstant(), ... ), but this won't always work.
* ts.toInstant() assumes the number of milliseconds since the epoch
* means the same thing in Timestamp and Instant, but it doesn't, in particular before 1900.
*/
return ts.toLocalDateTime().toLocalTime().atOffset( offset );
}

if ( Date.class.isInstance( value ) ) {
final Date date = (Date) value;
return OffsetTime.ofInstant( date.toInstant(), ZoneId.systemDefault() );
return OffsetTime.ofInstant( date.toInstant(), offset );
}

if ( Long.class.isInstance( value ) ) {
return OffsetTime.ofInstant( Instant.ofEpochMilli( (Long) value ), ZoneId.systemDefault() );
return OffsetTime.ofInstant( Instant.ofEpochMilli( (Long) value ), offset );
}

if ( Calendar.class.isInstance( value ) ) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,16 @@
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
import java.util.function.Consumer;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.hibernate.cfg.AvailableSettings;
import org.hibernate.cfg.Configuration;
import org.hibernate.dialect.Dialect;
import org.hibernate.dialect.H2Dialect;
import org.hibernate.dialect.MariaDB10Dialect;
import org.hibernate.dialect.Oracle8iDialect;
import org.hibernate.dialect.PostgreSQL81Dialect;
import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;

import org.hibernate.testing.TestForIssue;
Expand Down Expand Up @@ -216,10 +221,6 @@ else if ( cause instanceof Error ) {
}
}

protected final ZoneId getDefaultJvmTimeZone() {
return env.defaultJvmTimeZone;
}

protected final Class<? extends AbstractRemappingH2Dialect> getRemappingDialectClass() {
return env.remappingDialectClass;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
import java.time.ZoneOffset;
import java.util.Arrays;
import java.util.List;
import java.util.TimeZone;
import javax.persistence.Basic;
import javax.persistence.Column;
import javax.persistence.Entity;
Expand All @@ -31,7 +30,6 @@
import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor;

import org.hibernate.testing.SkipForDialect;
import org.hibernate.testing.SkipLog;
import org.junit.Test;
import org.junit.runners.Parameterized;

Expand Down Expand Up @@ -183,35 +181,13 @@ protected Object getActualJdbcValue(ResultSet resultSet, int columnIndex) throws
return resultSet.getTimestamp( columnIndex );
}

@Override
@Test
public void nativeWriteThenRead() {
if ( TimeAsTimestampRemappingH2Dialect.class.equals( getRemappingDialectClass() ) &&
!ZONE_GMT.equals( getDefaultJvmTimeZone() ) ) {
SkipLog.reportSkip( "OffsetTimeType remapped as timestamp only works reliably with GMT default JVM for nativeWriteThenRead; see HHH-13357" );
return;
}
super.nativeWriteThenRead();
}

@Override
@Test
@SkipForDialect(value = AbstractHANADialect.class, comment = "HANA seems to return a java.sql.Timestamp instead of a java.sql.Time")
public void writeThenNativeRead() {
super.writeThenNativeRead();
}

@Override
@Test
public void writeThenRead() {
if ( TimeAsTimestampRemappingH2Dialect.class.equals( getRemappingDialectClass() ) &&
!ZONE_GMT.equals( getDefaultJvmTimeZone() ) ) {
SkipLog.reportSkip( "OffsetTimeType remapped as timestamp only works reliably with GMT default JVM for writeThenRead; see HHH-13357" );
return;
}
super.writeThenRead();
}

@Entity(name = ENTITY_NAME)
static final class EntityWithOffsetTime {
@Id
Expand Down