Mysql сервер сохраняет LocalDateTime на 3 часа больше времени ОС - PullRequest
0 голосов
/ 04 мая 2019

Во время процесса записи сервиса LocaDateTime в базу данных, в моем случае в API весенней загрузки с Java 8, при сохранении атрибута, настроенного как TIMESTAMP на стороне базы данных, и LocaDateTime в API, эта датасохранено с 3 часами после текущей даты операционной системы.

Предположим, я пытаюсь сделать это ровно в 10 часов утра, дата, сохраненная в базе данных, должна быть 11 часов, но в моем случае это не работает, чтоспособ ...

private LocalDateTime dataLimite;

@PrePersist
public void prepareToSave() {
    String str = "1986-04-08 10:00";
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm");
    LocalDateTime dateTime = LocalDateTime.parse(str, formatter);
    this.dataLimite = dateTime.plusHours(1);
}

Date into the database Очевидно, можно заметить, что это проблема на стороне конфигурации Mysql, но когда я тестирую ...

SELECT NOW();

Результатом являются именно дата и время операционной системы, так в чем же заключается настоящая проблема?Как решить эту проблему?

1 Ответ

1 голос
/ 05 мая 2019

LocalDateTime

Внимательно прочитайте документацию.

Этот класс не хранит и не представляет часовой пояс. Вместо этого, это описание даты, используемой для дней рождений, в сочетании с местным временем, показанным на настенных часах. Он не может представлять момент на временной шкале без дополнительной информации, такой как смещение или часовой пояс.

Класс LocalDateTime в Java нельзя использовать для представления момента. Он представляет потенциальные моменты в диапазоне около 26-27 часов, диапазоне часовых поясов по всему земному шару.

Этот класс содержит дату и время суток, но намеренно не имеет понятия о часовом поясе или смещении от UTC. Поэтому, если вы храните, например, полдень 23 января этого года, мы не знаем, имели ли вы в виду полдень в Токио, Калькутте, Париже или Монреале ... все разные моменты, с разницей в часах, происходили раньше на востоке, а затем в Запад.

Итак, вы используете неправильный класс. На мгновение используйте Instant, OffsetDateTime или ZonedDateTime.

TIMESTAMP

Внимательно прочитайте документацию.

Тип TIMESTAMP в MySQL 8 похож на тип SQL-стандарта TIMESTAMP WITH TIME ZONE. Этот тип представляет момент, конкретную точку на временной шкале.

Документация объясняет , что момент, переданный в базу данных, настроен на UTC для хранения.

MySQL преобразует TIMESTAMP значений из текущего часового пояса в UTC для хранения и обратно из UTC в текущий часовой пояс для извлечения.

Это объясняет вашу проблему. Вы неявно полагались на то, что текущий часовой пояс по умолчанию назначается объекту неправильного типа в Java, в котором отсутствует какой-либо часовой пояс. Никогда не пишите код, который зависит от текущего часового пояса по умолчанию (или локали) вашего сервера, так как он находится вне вашего контроля программиста. Вместо этого всегда указывайте явно желаемый / ожидаемый часовой пояс. Или лучше, просто по возможности работайте в UTC.

Для получения наилучших результатов придерживайтесь UTC при обмене значениями с базой данных.

OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;

myPreparedStatement.setObject( … , odt ) ;

индексирование.

OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;

Чтобы просмотреть этот момент через часы настенного времени, используемые людьми определенного региона, примените ZoneId, чтобы получить ZonedDateTime.

ZoneId z = ZoneId.of( "Australia/Sydney" ) ;
ZonedDateTime zdt = odt.atZoneSameInstant( z ) ;

Table of date-time types in Java (both modern and legacy) and in standard SQL.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...