Using ZonedDateTime with datetimeoffset in SQLServer

Tyler Murry :

I have an application that uses a SQLServer database with datetimeoffset columns. Preferably, I would like to use ZonedDateTime as my JPA entity object type like so:

@Column(name = "CreateTimestamp", nullable = false)
ZonedDateTime createTimestamp;

However, the timezone is not being properly saved. No matter what I set the ZoneId to in the ZonedDateTime, the value will always be in GMT in the database.

Looking at Microsoft's JDBC mapping diagram, the recommended class to use is microsoft.sql.DateTimeOffset which is not what I would prefer.

I've explored using a @Converter to map between the two, but having to provide special knowledge like this seems like a red flag that I'm doing something wrong - especially since I need this to work inside of an integration test using H2.

What is the best way to use datetimeoffset and ZonedDateTime in a vendor agnostic way?

Tyler Murry :

I hate to answer my own question but I want to make sure the solution is documented.

The solution is to use a @Converter to transform a ZonedDateTime into a String. Hibernate will pass this down to SQLServer as a VARCHAR and the database itself will implicitly convert the value into a datetimeoffset - the same way it converts a hardcoded date when you execute a standalone query.

The following converter worked for my circumstances:

@Converter(autoApply = true)
public class ZonedDateTimeConverter implements AttributeConverter<ZonedDateTime, String>
{
    private static final String DATE_FORMAT = "yyyy-MM-dd HH:mm:ss.SSSSSSS xxx";

    @Override
    public String convertToDatabaseColumn(ZonedDateTime zonedDateTime)
    {
        return DateTimeFormatter.ofPattern(DATE_FORMAT).format(zonedDateTime);
    }

    @Override
    public ZonedDateTime convertToEntityAttribute(String dateAsString)
    {
        return ZonedDateTime.parse(dateAsString, DateTimeFormatter.ofPattern(DATE_FORMAT));
    }
}

Additionally, this also works in H2 so it can be used inside of an integration test without having to do any vendor-specific logic.

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=476547&siteId=1