Ответ Sacre правильный, но устаревший. Современный способ - с классами java.time.
ТЛ; др
StringBuild sql = new StringBuilder()
sql.append( "SELECT id_, datum_ " );
sql.append( "FROM appointments_ " );
sql.append( "WHERE datum_ >= ? " ); // Start is *inclusive*…
sql.append( "AND datum_ < ? ; " ); // …while end is *exclusive*. (Half-Open approach)
И передать пару Instant
объектов.
pstmt.setObject( 1 , start ) ; // Pass `java.time.Instant` object directly via `PreparedStatement::setObject` method.
pstmt.setObject( 2 , stop ) ;
Использовать объекты, а не строки
Избегайте использования строк для извлечения / хранения значений даты и времени в вашей базе данных. Используйте объекты даты и времени для значений даты и времени. Java и JDBC имеют богатую поддержку объектов даты и времени.
Использование java.time
Класс java.sql.Date
предназначен для представления значения только для даты без времени суток и без часового пояса. На самом деле он несет в себе оба этих дополнения, но делает вид, что не слишком. Современная замена - LocalDate
. Класс LocalDate
представляет значение только для даты без времени суток и без часового пояса.
Но java.sql.Date
(и LocalDate
тоже) является неправильным классом для использования, поскольку ваш столбец, похоже, определяется не как только для даты , а как дата-время тип.
Критическая проблема здесь игнорируется вашим Вопросом: часовой пояс. Часовой пояс имеет решающее значение при определении даты . В любой момент времени дата меняется по всему земному шару в зависимости от зоны. Например, через несколько минут после полуночи в Париж Франция - это новый день, а еще «вчера» в Монреаль Квебек .
Укажите собственное имя часового пояса в формате continent/region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
. Никогда не используйте 3-4-буквенное сокращение, например EST
или IST
, поскольку они не истинных часовых поясов, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );
Относительно часового пояса в вашей базе данных ...
- Ваша база данных почти наверняка хранит значения даты и времени, переносящие информацию о часовом поясе или смещении от UTC, как значения UTC в типе, таком как стандарт SQL
TIMESTAMP WITH TIME ZONE
.
- Если используется
TIMESTAMP WITHOUT TIME ZONE
, то значения не имеют информации о часовом поясе или смещении от UTC и не представляют фактических моментов на временной шкале, но могут подходить для встреч достаточно далеко в будущем, в которых они сохраняются как зонированные значения несут в себе риск столкновения политиков с изменением определения часового пояса, например с настройкой / принятием / отменой перехода на летнее время.
Если они хранятся в виде зонированных значений, вам необходимо определить начальный и конечный моменты вашей даты в желаемом часовом поясе, затем преобразовать эту пару точек в значения UTC и запросить в базе данных эту пару значений UTC.
Как правило, лучшая практика в работе с датой и временем для определения промежутков времени, таких как продолжительность дня, как это необходимо здесь, заключается в использовании подхода Half-Open, когда начало промежутка составляет включительно в то время как окончание исключительное . Таким образом, день начинается с первого момента дня и доходит, но не включает первый момент следующего дня.
Не думайте, что первый момент дня - 00:00:00. Аномалии, такие как летнее время (DST), означают, что день может начинаться в такое время, как 01:00:00. Пусть java.time определит первый момент дня.
ZonedDateTime startZdt = localDate.atStartOfDay( z );
ZonedDateTime stopZdt = localDate.plusDays( 1 ).atStartOfDay( z );
Также помните, что промежуток времени между этим стартом и остановкой не обязательно равен 24 часам. Аномалии, такие как летнее время, означают, что день может длиться 23 или 25 часов или какой-либо другой продолжительности.
Преобразуйте их в UTC, извлекая объект Instant
. Класс Instant
представляет момент на временной шкале в UTC с разрешением наносекунд (до девяти (9) цифр десятичной дроби).
Instant start = startZdt.toInstant(); // Convert to UTC value.
Instant stop = stopZdt.toInstant();
Чтобы выполнить запрос SQL, выполните , а не , используйте BETWEEN
. Вместо подхода Half-Open эта команда использует метод Closed, в котором начало и конец включаются.
StringBuild sql = new StringBuilder()
sql.append( "SELECT id_, datum_ " );
sql.append( "FROM appointments_ " );
sql.append( "WHERE datum_ >= ? " ); // Start is *inclusive*…
sql.append( "AND datum_ < ? ; " ); // …while end is *exclusive*. (Half-Open approach)
PreparedStatement pstmt = conn.prepareStatement( sql.toString() );
Укажите пару объектов Instant
в качестве аргументов, которые будут использоваться оператором SQL.
pstmt.setObject( 1 , start ) ; // Pass java.time.Instant object directly via `setObject` method.
pstmt.setObject( 2 , stop ) ;
Боковая панель: добавьте завершающее подчеркивание ко всем вашим идентификаторам SQL, чтобы избежать любого конфликта имен с тысячей зарезервированных слов, согласно обещанию в спецификации SQL.
НетТо есть, как мы вызывали setObject
, чтобы напрямую связываться с нашими типами java.time в JDBC.
Если ваш драйвер JDBC еще не поддерживает JDBC 4.2 или более поздней версии, вы должны использовать устаревшие типы java.sql. В этом случае нам понадобится java.sql.Timestamp
. Но сделайте это ненадолго - постарайтесь как можно дольше оставаться в java.time.
pstmt.setTimestamp( 1 , java.sql.Timestamp.from( start ) ) ;
pstmt.setTimestamp( 2 , java.sql.Timestamp.from( stop ) ) ;
О java.time
Фреймворк java.time встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , в настоящее время находящийся в режиме обслуживания , рекомендует перейти на java.time классы.
Чтобы узнать больше, см. Oracle Tutorial . И поиск переполнения стека для многих примеров и объяснений. Спецификация JSR 310 .
Где получить классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами. Этот проект является полигоном для возможных будущих дополнений к java.time. Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more .