Я использую сервер MySQL, который находится в том же часовом поясе, что и я. Я пытаюсь вставить java.util.Date в базу данных по столбцу типа DATE со следующим кодом:

SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd"); dateFormat.setTimeZone(TimeZone.getTimeZone("GMT+2")); Date date = dateFormat.parse(map.value("date"));

Где "дата" вставлена. Проблема в том, что при просмотре в базе данных дата выключается на один день. Пример: я вставил 2020-05-02, база данных показывает 2020-05-01. Это создает проблему, заключающуюся в том, что, когда я хочу получить совпадения с датой 2020-05-02, мне приходится искать на 1 день раньше, что я не хочу делать. Также это происходит между определенными временами в день, так что я предполагаю, что это проблема часового пояса, но я не знаю, как это исправить!

Подсказки?

3
Teh Swish 2 Май 2020 в 17:47

2 ответа

Лучший ответ

Эта проблема исходит от MySQL Connector в Java. Версия 8.0.19 преобразует дату, используя часовой пояс JVM, что приводит к проблеме 1 выходного дня. Это решено в патче 8.0.20. Читайте здесь https://dev.mysql.com/doc/relnotes /connector-j/8.0/en/

2
Teh Swish 4 Май 2020 в 15:17

Для значения только для даты, без времени суток и без часового пояса, вы должны использовать тип MySQL DATE при определении вашего столбца. Этот тип соответствует типу DATE, определенному в стандарте SQL.

На стороне Java никогда не используйте java.util.Date. Этот класс является частью ужасных классов даты и времени, связанных с ранними версиями Java. Несколько лет назад их вытеснили классы java.time , определенные в JSR 310.

Для значения только даты в Java используйте java.time.LocalDate.

На вашей карте вы должны хранить объект LocalDate, а не просто строку. Но если вам нужно, вы можете анализировать и генерировать строки. Формат ваших строк, кажется, совпадает со стандартным форматом, определенным в ISO 8601. Классы java.time используют эти стандартные форматы по умолчанию. Поэтому нет необходимости указывать шаблон форматирования.

LocalDate localDate = LocalDate.parse( "2021-01-23" ) ;

Объекты классов java.time можно обменять с вашей базой данных с помощью JDBC драйвер совместим с JDBC 4.2 и более поздними версиями.

Запишите это в базу данных.

myPreparedStatement.setObject( … , localDate ) ;

Получить из базы данных.

LocalDate localDate = myResultSet.getObject( … , LocalDate.class ) ;

Использование подхода, показанного выше, делает часовые пояса нерелевантными: LocalDate через JDBC 4.2 или более поздней версии в столбце типа MySQL DATE - то есть, если вы не Драйвер JDBC является глючит (ошибка # 30877755): см. ответ Teh Swish.

2
Basil Bourque 4 Май 2020 в 21:28