From 30ceca18c2654a80c6355c9a7c735d9667309255 Mon Sep 17 00:00:00 2001 From: Steve Ebersole Date: Tue, 24 Mar 2015 20:25:17 -0500 Subject: [PATCH] HHH-8844 - Add support for Java 8 date and time types (JSR-310) --- hibernate-c3p0/hibernate-c3p0.gradle | 1 - .../type/Java8DateTimeTypeContributor.java | 1 + .../org/hibernate/type/OffsetTimeType.java | 85 +++++++++++ .../java/OffsetTimeJavaDescriptor.java | 138 ++++++++++++++++++ .../test/type/Java8DateTimeTests.java | 10 ++ 5 files changed, 234 insertions(+), 1 deletion(-) create mode 100644 hibernate-java8/src/main/java/org/hibernate/type/OffsetTimeType.java create mode 100644 hibernate-java8/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaDescriptor.java diff --git a/hibernate-c3p0/hibernate-c3p0.gradle b/hibernate-c3p0/hibernate-c3p0.gradle index a668bf9790..fb39498f1f 100644 --- a/hibernate-c3p0/hibernate-c3p0.gradle +++ b/hibernate-c3p0/hibernate-c3p0.gradle @@ -1,5 +1,4 @@ dependencies { - provided( libraries.validation ) compile project( ':hibernate-core' ) compile( libraries.c3p0 ) diff --git a/hibernate-java8/src/main/java/org/hibernate/type/Java8DateTimeTypeContributor.java b/hibernate-java8/src/main/java/org/hibernate/type/Java8DateTimeTypeContributor.java index 3f89d0caa8..79525572f8 100644 --- a/hibernate-java8/src/main/java/org/hibernate/type/Java8DateTimeTypeContributor.java +++ b/hibernate-java8/src/main/java/org/hibernate/type/Java8DateTimeTypeContributor.java @@ -43,5 +43,6 @@ public class Java8DateTimeTypeContributor implements TypeContributor { typeContributions.contributeType( ZonedDateTimeType.INSTANCE ); typeContributions.contributeType( OffsetDateTimeType.INSTANCE ); + typeContributions.contributeType( OffsetTimeType.INSTANCE ); } } \ No newline at end of file diff --git a/hibernate-java8/src/main/java/org/hibernate/type/OffsetTimeType.java b/hibernate-java8/src/main/java/org/hibernate/type/OffsetTimeType.java new file mode 100644 index 0000000000..a348e3a8c2 --- /dev/null +++ b/hibernate-java8/src/main/java/org/hibernate/type/OffsetTimeType.java @@ -0,0 +1,85 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2015, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.type; + +import java.time.OffsetTime; +import java.time.format.DateTimeFormatter; +import java.util.Comparator; +import java.util.Locale; + +import org.hibernate.dialect.Dialect; +import org.hibernate.engine.spi.SessionImplementor; +import org.hibernate.internal.util.compare.ComparableComparator; +import org.hibernate.type.descriptor.java.OffsetTimeJavaDescriptor; +import org.hibernate.type.descriptor.sql.TimestampTypeDescriptor; + +/** + * @author Steve Ebersole + */ +public class OffsetTimeType + extends AbstractSingleColumnStandardBasicType + implements VersionType, LiteralType { + + /** + * Singleton access + */ + public static final OffsetTimeType INSTANCE = new OffsetTimeType(); + + public static final DateTimeFormatter FORMATTER = DateTimeFormatter.ofPattern( "HH:mm:ss.S xxxxx", Locale.ENGLISH ); + + public OffsetTimeType() { + super( TimestampTypeDescriptor.INSTANCE, OffsetTimeJavaDescriptor.INSTANCE ); + } + + @Override + public String objectToSQLString(OffsetTime value, Dialect dialect) throws Exception { + return "{ts '" + FORMATTER.format( value ) + "'}"; + } + + @Override + public OffsetTime seed(SessionImplementor session) { + return OffsetTime.now(); + } + + @Override + public OffsetTime next(OffsetTime current, SessionImplementor session) { + return OffsetTime.now(); + } + + @Override + @SuppressWarnings("unchecked") + public Comparator getComparator() { + return ComparableComparator.INSTANCE; + } + + @Override + public String getName() { + return OffsetTime.class.getSimpleName(); + } + + @Override + protected boolean registerUnderJavaType() { + return true; + } +} diff --git a/hibernate-java8/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaDescriptor.java b/hibernate-java8/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaDescriptor.java new file mode 100644 index 0000000000..ab85e19d24 --- /dev/null +++ b/hibernate-java8/src/main/java/org/hibernate/type/descriptor/java/OffsetTimeJavaDescriptor.java @@ -0,0 +1,138 @@ +/* + * Hibernate, Relational Persistence for Idiomatic Java + * + * Copyright (c) 2015, Red Hat Inc. or third-party contributors as + * indicated by the @author tags or express copyright attribution + * statements applied by the authors. All third-party contributions are + * distributed under license by Red Hat Inc. + * + * This copyrighted material is made available to anyone wishing to use, modify, + * copy, or redistribute it subject to the terms and conditions of the GNU + * Lesser General Public License, as published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License + * for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this distribution; if not, write to: + * Free Software Foundation, Inc. + * 51 Franklin Street, Fifth Floor + * Boston, MA 02110-1301 USA + */ +package org.hibernate.type.descriptor.java; + +import java.sql.Timestamp; +import java.time.Instant; +import java.time.LocalDate; +import java.time.OffsetTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.util.Calendar; +import java.util.Date; +import java.util.GregorianCalendar; + +import org.hibernate.type.OffsetTimeType; +import org.hibernate.type.descriptor.WrapperOptions; + +/** + * Java type descriptor for the LocalDateTime type. + * + * @author Steve Ebersole + */ +public class OffsetTimeJavaDescriptor extends AbstractTypeDescriptor { + /** + * Singleton access + */ + public static final OffsetTimeJavaDescriptor INSTANCE = new OffsetTimeJavaDescriptor(); + + @SuppressWarnings("unchecked") + public OffsetTimeJavaDescriptor() { + super( OffsetTime.class, ImmutableMutabilityPlan.INSTANCE ); + } + + @Override + public String toString(OffsetTime value) { + return OffsetTimeType.FORMATTER.format( value ); + } + + @Override + public OffsetTime fromString(String string) { + return (OffsetTime) OffsetTimeType.FORMATTER.parse( string ); + } + + @Override + @SuppressWarnings("unchecked") + public X unwrap(OffsetTime offsetTime, Class type, WrapperOptions options) { + if ( offsetTime == null ) { + return null; + } + + if ( OffsetTime.class.isAssignableFrom( type ) ) { + return (X) offsetTime; + } + + final ZonedDateTime zonedDateTime = offsetTime.atDate( LocalDate.of( 1970, 1, 1 ) ).toZonedDateTime(); + + if ( Calendar.class.isAssignableFrom( type ) ) { + return (X) GregorianCalendar.from( zonedDateTime ); + } + + final Instant instant = zonedDateTime.toInstant(); + + if ( Timestamp.class.isAssignableFrom( type ) ) { + return (X) Timestamp.from( instant ); + } + + if ( java.sql.Date.class.isAssignableFrom( type ) ) { + return (X) java.sql.Date.from( instant ); + } + + if ( java.sql.Time.class.isAssignableFrom( type ) ) { + return (X) java.sql.Time.from( instant ); + } + + if ( Date.class.isAssignableFrom( type ) ) { + return (X) Date.from( instant ); + } + + if ( Long.class.isAssignableFrom( type ) ) { + return (X) Long.valueOf( instant.toEpochMilli() ); + } + + throw unknownUnwrap( type ); + } + + @Override + public OffsetTime wrap(X value, WrapperOptions options) { + if ( value == null ) { + return null; + } + + if ( OffsetTime.class.isInstance( value ) ) { + return (OffsetTime) value; + } + + if ( Timestamp.class.isInstance( value ) ) { + final Timestamp ts = (Timestamp) value; + return OffsetTime.ofInstant( ts.toInstant(), ZoneId.systemDefault() ); + } + + if ( Date.class.isInstance( value ) ) { + final Date date = (Date) value; + return OffsetTime.ofInstant( date.toInstant(), ZoneId.systemDefault() ); + } + + if ( Long.class.isInstance( value ) ) { + return OffsetTime.ofInstant( Instant.ofEpochMilli( (Long) value ), ZoneId.systemDefault() ); + } + + if ( Calendar.class.isInstance( value ) ) { + final Calendar calendar = (Calendar) value; + return OffsetTime.ofInstant( calendar.toInstant(), calendar.getTimeZone().toZoneId() ); + } + + throw unknownWrap( value.getClass() ); + } +} diff --git a/hibernate-java8/src/test/java/org/hibernate/test/type/Java8DateTimeTests.java b/hibernate-java8/src/test/java/org/hibernate/test/type/Java8DateTimeTests.java index 26f1cc7e4a..25bf7addeb 100644 --- a/hibernate-java8/src/test/java/org/hibernate/test/type/Java8DateTimeTests.java +++ b/hibernate-java8/src/test/java/org/hibernate/test/type/Java8DateTimeTests.java @@ -28,6 +28,7 @@ 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.Iterator; import javax.persistence.Entity; @@ -113,6 +114,7 @@ public class Java8DateTimeTests extends BaseNonConfigCoreFunctionalTestCase { private Instant instant = Instant.now(); private ZonedDateTime zonedDateTime = ZonedDateTime.now(); private OffsetDateTime offsetDateTime = OffsetDateTime.now(); + private OffsetTime offsetTime = OffsetTime.now(); public TheEntity() { } @@ -177,5 +179,13 @@ public class Java8DateTimeTests extends BaseNonConfigCoreFunctionalTestCase { public void setOffsetDateTime(OffsetDateTime offsetDateTime) { this.offsetDateTime = offsetDateTime; } + + public OffsetTime getOffsetTime() { + return offsetTime; + } + + public void setOffsetTime(OffsetTime offsetTime) { + this.offsetTime = offsetTime; + } } }