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.