Java SQL дата выключена на 1 день - PullRequest
2 голосов
/ 02 мая 2020

Я использую сервер 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 день раньше, что я не хочу делать. Также это происходит между определенными c раз в день, так что я предполагаю, что это проблема часового пояса, но я не знаю, как ее исправить!

Советы?

Ответы [ 2 ]

3 голосов
/ 04 мая 2020

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

3 голосов
/ 02 мая 2020

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

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

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

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

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

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

Запись этого в базу данных.

myPreparedStatement.setObject( … , localDate ) ;

Извлечение из базы данных.

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

Использование подхода, показанного выше, делает часовые пояса нерелевантными: LocalDate через JDB C 4.2 или новее для столбца типа MySQL DATE - То есть, если ваш JDB C драйвер is buggy (Bug # 30877755): См. Answer by Teh Swi sh.

...