Ответ 1
Вопрос и другие ответы, похоже, слишком задумываются над этой проблемой. A java.sql.Date - это просто java.util. Дата с установленным временем 00:00:00
.
Из java.sql.Date doc (курсив мой текст)...
Дата класса
java.lang.Object
java.util.Date ← Наследует от j.u.Date
java.sql.Date
...
Тонкая обертка вокруг значения миллисекунды, которая позволяет JDBC идентифицировать это как значение DATE SQL. Значение миллисекунды представляет собой миллисекунды, прошедшие с 1 января 1970 года 00: 00: 00.000 GMT. ← Время суток установлено на ноль, полночь GMT/UTC
Чтобы соответствовать определению SQL DATE, значения миллисекунды, обернутые экземпляром java.sql.Date, должны быть "нормализованы", установив часы, минуты, секунды и миллисекунды на ноль в конкретном часовом поясе, с которым экземпляр связан.
Дата-только против даты-времени
Основная проблема:
- SQL
В SQL тип данныхDATE
хранит дату-только, без времени суток. - JAVA
В плохо спроектированной библиотеке с датами, в комплекте с ранними версиями Java, они не включили класс для представления даты.
Вместо создания класса с датой команда Java сделала ужасный взлом. Они взяли свой класс времени (класс java.util.Date
, содержащий как дату, так и время) и расширили его, чтобы экземпляр задал свое время от дня до полуночи UTC, 00:00:00
. Этот хак, этот подкласс j.u.Date, java.sql.Date
.
Все эти взломы, плохой дизайн и неправильное использование сделали путаницу.
Что использовать
Итак, когда использовать какой? Простой, пробив путаницу.
- При чтении или записи в базу данных столбца с датой только используйте
java.sql.Date
, поскольку он неуклюже пытается замаскировать свое время суток. - Всюду в Java, где вам нужно время в день вместе с вашей датой, используйте
java.util.Date
. - Когда у вас есть java.sql.Date в руке, но вам нужен java.util.Date, просто передайте java.sql.Date. В качестве подкласса java.sql.Date является java.util.Date.
Еще лучше
В современной Java вы знаете, что у вас есть выбор подходящих библиотек времени, чтобы вытеснить старые и печально известные проблемы java.util.Date,.Calendar, SimpleTextFormat и java.sql.Date классы в комплекте с Java. Основные варианты:
- Joda-Time
- java.time
(вдохновлено Joda-Time, определенный JSR 310, в комплекте с Java 8, расширенный проектом ThreeTen-Extra)
Оба предлагают класс LocalDate
для представления только даты, без времени и без часовой пояс.
В конце концов драйверы JDBC будут обновлены, чтобы напрямую использовать новые типы данных java.time. Затем мы можем полностью отказаться от уродливого беспорядка, который является классами даты и времени в пакетах java.util. * И java.sql. *.
Модернизированный JDBC
Надеюсь, JDBC будет обновлен, чтобы предоставлять методы getter и setter для java.time LocalDate.
setObject | GetObject
Эта статья, опубликованная Oracle, показывает, что JDBC в Java 8 прозрачно обновлялся, чтобы сопоставить значение SQL DATE
с новым java.time.LocalDate, если вы вызываете методы getObject
и setObject
.
В тупых словах нижняя часть toInstant()
toLocalDate()
public static Date valueOf(java.time.LocalDate)
Часовой пояс
старые классы временив Java (java.util.Date/.Calendar, java.sql.Date/.Timestamp и т.д. до java.time) не имеют часового пояса практически. Некоторые часового пояса глубоко погружены в исходный код, но игнорируются для большинства целей. Наиболее смутно, их методы toString
применяют текущий часовой пояс JVM. Поэтому для наивного программиста кажется, что у них есть часовой пояс, но они этого не делают.
Избегать классов времени по дате В java.util. * и java.sql. *
Эта проблема с часовым поясом является одной из многих причин избежать j.u.Date/Calendar и j.sql.Date/Timestamp, когда это возможно. Напишите свою бизнес-логику, используя java.time (Java 8 и более поздние версии). Там, где отсутствует java.time, используйте Joda-Time. Как java.time, так и Joda-Time имеют удобные методы для возврата туда и обратно со старыми классами, где это необходимо.