persistence icon indicating copy to clipboard operation
persistence copied to clipboard

Support for java.time.Instant

Open lukasj opened this issue 7 years ago • 6 comments

Original issue #63 mentioned support for java.time.Instant but it's missing in the final 2.2 spec. I haven't found any reason for omitting it.

I feel it's important for supporting pure UTC data flow as described in the #156. Instant already stores epoch internally so it cleanly maps to a UTC timestamp and it would simplify such use case rather than converting back and forth between different (application, database, user) time zones.

I believe that Instant as a machine-timeline view should be the recommended approach for persisting time data over LocalDateTime, OffsetDateTime, ZonedDateTime which are human-timeline views.

Hibernate supports Instant just fine already and allows changing the database timezone via hibernate.jdbc.time_zone.

lukasj avatar Oct 18 '17 09:10 lukasj

  • Issue Imported From: https://github.com/javaee/jpa-spec/issues/163
  • Original Issue Raised By:@jacekkruger
  • Original Issue Assigned To: Unassigned

lukasj avatar Aug 31 '18 16:08 lukasj

@ghost Commented Of all the java.time types, it is Instant that is designed exactly to represent a point in time, so it should be supported. It is also the only type that is suitable for conversion from and to java.sql.Timestamp. Of the newly supported types LocalDate, LocalTime, LocalDateTime, OffsetTime and OffsetDateTime, only the latter actually represents a point in time, but cannot be created from a Timestamp alone (the offset is missing).

So if you want to persist a point of time with JPA 2.2, the following options appear to me:

  • Use java.util.Date
  • Use OffsetDateTime, but this forces you to choose an offset for all your values. You can use ZoneOffset.UTC for all, basically reducing OffsetDateTime to an Instant. Also, not all popular database systems support persisting an offset along the timestamp value, so you might need to use @javax.persistence.TemporalTimeZoneColumn, scattering the value among two columns.
  • Use Instant and an AttributeConverter, as you already could do before JPA 2.2

Supporting Instant sounds preferable to each of these.

lukasj avatar Jan 24 '18 18:01 lukasj

For others wishing Instants were supported directly, here is my code to support it using an AttributeConverter, as recommended as a stopgap by @lukasj above. `package Repository;

import javax.persistence.AttributeConverter; import javax.persistence.Converter; import java.sql.Timestamp; import java.time.Instant;

@Converter(autoApply = true) public class InstantAttributeConverter implements AttributeConverter<Instant, Timestamp> {

@Override
public Timestamp convertToDatabaseColumn(Instant instant) {
    if (instant == null)
        return null;
    else
    {
        Timestamp t = Timestamp.from(instant);
        return t;
    }
}

@Override
public Instant convertToEntityAttribute(Timestamp timestamp) {
    //System.out.println(timestamp + " " + timestamp.toInstant() + " " + timestamp.getTimezoneOffset());
    return (timestamp == null ? null : timestamp.toInstant());
}

}`

psyklopz avatar Dec 06 '18 20:12 psyklopz

@psyklopz Unfortunately this approach does not work correctly with all databases. On Microsoft SQL Server for example you will get local time instead of UTC.

sergeykad avatar Dec 07 '18 13:12 sergeykad

@sergeykad Great point. By convention all our servers are set to UTC. When running on a local dev machine, we pass the time zone (UTC) as part of our connection string to the MySQL JDBC driver.

Maybe I worry more than I should, but I don't trust that time zone conversions done in Java are always consistent with those done in the database.

I also get uncomfortable that converting from UTC to local and back to UTC is not foolproof. In the hour before (or after) daylight savings we have a wrinkle in time.

I wish databases had no concept of time zones. That belongs in the presentation layer and not in the business layers. But I digress...

Use my sample code if and only if your database and your Java code are both running in UTC.

psyklopz avatar Dec 08 '18 01:12 psyklopz

I am in favor of adding support for Instant to JPA specs.

sharmasourabh avatar Jan 15 '20 11:01 sharmasourabh

@lukasj I agree that we should totally do this.

gavinking avatar Aug 08 '23 18:08 gavinking

I've proposed support for Instant and Year in https://github.com/jakartaee/persistence/pull/434.

Note that it's clear why Instant was left out of previous revisions of JPA: the JDBC spec does not mention it in Appendix B. But in fact there are other missing type mappings in the JDBC spec, so what I've done is also nailed down the missing type mappings.

gavinking avatar Aug 09 '23 09:08 gavinking