Using ZonedDateTime with datetimeoffset in SQLServer

A bit of a gotchya here. The data time ZoneDateTime contains more information than an OffsetDateTime. The zone. Mind you, a zone is not the same as an offset. It is more. Two zones could, at a given moment, have the same offset, but months later, one zone "springs forward" the other zone does not. Or, they spring forward on different days. In converting a string from an OffsetDateTime to a ZoneDateTime, you are introducing a zone where one did not exist before.


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.