Неправильный тип
Вы используете неверный тип данных для своего столбца.
Тип datetime2
не может представлять момент. Этот тип хранит только дату и время дня, но не имеет контекста часового пояса или смещения от UTC,Поэтому, если вы храните «полдень 23 января 2020 года», мы не можем знать, имели ли вы в виду полдень в Токио, Япония, полдень в Тунисе, Тунис, или полдень в Толедо, штат Огайо, США, три разных момента с интервалом в несколько часов.Этот неправильный тип похож на стандартный тип SQL TIMESTAMP WITHOUT TIME ZONE
.Эквивалентный класс в Java - LocalDateTime
.
Если у вас уже есть данные, вам необходимо реорганизовать вашу базу данных .По сути, добавьте новый столбец правильного типа, скопируйте данные для каждой строки, конвертируя по ходу работы.Конечно, это работает, только если вы знаете предполагаемый часовой пояс, который отсутствовал в каждом сохраненном значении.
Правильный тип
Хотя я не использую Microsoft SQL Server, в соответствии с документом вы должны использовать столбец типа datetimeoffset
для записи момента .Этот тип корректирует любое переданное значение в UTC для запросов и сортировки, а также записывает смещение.Этот тип похож на стандартный тип SQL TIMESTAMP WITH TIME ZONE
.
Обычно лучше всего хранить свои моменты в формате UTC, смещение нуля часов, минут и секунд.
Класс Instant
представляет момент в UTC.
Instant instant = Instant.now() ;
Если у вас есть ZonedDateTime
, вы можете извлечь Instant
.
Instant instant = zdt.toInstant() ;
Мы хотели бы сохранить это Instant
непосредственно в базе данных.К сожалению, для JDBC 4.2 soec не требуется поддержка ни одного из двух наиболее часто используемых java.time классов: Instant
и ZonedDateTime
.Спецификация требует поддержки OffsetDateTime
.Итак, мы конвертируем.
OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;
Добавить в базу данных.
myPreparedStatement.setObject( … , odt ) ;
Retrieve.
OffsetDateTime odt = MyResultSet.getObject( … , OffsetDateTime.class ) ;
Извлеките Instant
, чтобы указать в своем коде, что вы хотите использовать UTC.
Instant instant = odt.toInstant() ;
Посмотрите этот момент через настенные часы, используемые людьми определенного региона (часового пояса).
ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;