Фильтр в SQL
Итак, я использую API Java Streams и пытаюсь отфильтровать даты в моей БД,
Это противоречие,Если вы фильтруете даты в базе данных как часть вашего запроса (как правило, лучший подход), тогда вам не нужны потоки Java.
Полуоткрытый запрос в SQL
Напишите ваш запрос,Я предполагаю, что мы запрашиваем пару столбцов типа данных, аналогичного стандарту SQL DATE
, для значения только для даты без времени суток и без часового пояса.
InВ этом коде запроса мы используем подход Half-Open, где начало включительно , а окончание эксклюзивно .Как правило, это лучший подход к обработке промежутков времени.
String sql = "SELECT * FROM event_ WHERE start_ <= ? AND stop_ > ? ;" ;
Today
Нам нужна сегодняшняя дата, чтобы перейти в этот ?
заполнитель.
Aчасовой пояс имеет решающее значение при определении даты.В любой момент времени дата меняется по всему миру в зависимости от зоны.Например, через несколько минут после полуночи в Париж Франция - это новый день, в то время как "вчера" в Монреаль Квебек .
Если часовой пояс не указан,JVM неявно применяет свой текущий часовой пояс по умолчанию.Это значение по умолчанию может измениться в любой момент во время выполнения (!), Поэтому ваши результаты могут отличаться.Лучше явно указать желаемый / ожидаемый часовой пояс в качестве аргумента.Если критично, подтвердите зону с вашим пользователем.
Укажите правильное имя часового пояса в формате Continent/Region
, например America/Montreal
, Africa/Casablanca
или Pacific/Auckland
,Никогда не используйте 2-4 буквенные сокращения, такие как EST
или IST
, так как они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
Если вы хотите использовать текущий часовой пояс JVM по умолчанию, запросите его и передайте в качестве аргумента.Если опущен, код становится неоднозначным для чтения, поскольку мы точно не знаем, намеревались ли вы использовать значение по умолчанию или если вы, как и многие программисты, не знали об этой проблеме.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
LocalDate today = LocalDate.now( z ) ;
Передать значениедля заполнителя
У нас есть сегодняшняя дата, поэтому передайте ее в подготовленную выписку.
myPreparedStatement.setObject( 1 , today ) ;
myPreparedStatement.setObject( 2 , today ) ;
Фильтр в Java
Как правило, лучше выполнять как можно больше фильтрации в пределахваш SQL, чтобы выполнить на стороне сервера в базе данных.Мощные движки баз данных корпоративного качества, такие как Postgres , высоко оптимизированы именно для такой работы.
Но, возможно, у вас есть причина сделать это в Java, а не в базе данных.
Вы должны извлекать строку за строкой в Java, извлекать из набора результатов в JDBC .Таким образом, вы могли бы также фильтровать тогда.Это означает, что нет необходимости в потоках Java.Просто сравните значения LocalDate
для начальных и конечных значений.
Я пытался реализовать интерфейс ChronoLocalDate и использовал .isBefore () и.isAfter () `, но даты сделалине отфильтрован должным образом
Вы, похоже, не понимаете, как java.time работает в этом отношении. Интерфейс ChronoLocalDate
не предназначен для реализации . Интерфейс уже реализован в классе LocalDate
для ISO 8601 календарная система, широко используемая на западе большей части остального мира.Этот интерфейс существует для авторов, реализующих различные системы составления календаря, а не для вас и для меня. По крайней мере, около десятка таких систем составления календарей уже реализованы для Java, включая некоторые в комплекте с Java, такие как исламские, японские и тайские календари.
Кстати, JavaDoc java.time объясняет, что в общем случае следует избегать использования более общих интерфейсов.Они существуют в основном для тех, кто внедряет системы календаря, как описано выше.В повседневном деловом программировании вы обычно должны использовать более конкретные классы.Например, LocalDate
вместо ChronoLocalDate
.
Ксравнить LocalDate
объекты, вызвать LocalDate::isBefore
, isAfter
, isEqual
, equals
или compareTo
методы
List< Event > events = new ArrayList<>() ;
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
…
LocalDate start = rs.getObject( "start_" , LocalDate.class ) ;
LocalDate stop = rs.getObject( "stop_" , LocalDate.class ) ;
if( ( ! start.isAfter( today ) ) && ( stop.isBefore( today ) ) {
Event event = … ;
events.add( event ) ;
} else {
// Skip this row. Does not meet our criterion of containing today's date.
}
}
LocalDateRange
Такая работа облегчается с помощью библиотеки ThreeTen-Extra . Этот проект добавляет функциональность классам java.time .
Для вашей конкретной ситуации вам может пригодиться класс LocalDateRange
. Этот класс представляет промежуток времени в виде пары LocalDate
объектов. Полезные методы сравнения включают abuts
, contains
, overlaps
и т. Д. Они работают по умолчанию в соответствии с подходом Half-Open, хотя при желании вы можете указать полностью закрытый (начало и конец включительно ).
Давайте использовать этот класс для изменения сравнения в нашем примере кода выше.
List< Event > events = new ArrayList<>() ;
ResultSet rs = stmt.executeQuery(query);
while (rs.next()) {
…
LocalDate start = rs.getObject( "start_" , LocalDate.class ) ;
LocalDate stop = rs.getObject( "stop_" , LocalDate.class ) ;
LocalDateRange dateRange = LocalDateRange.of( start , stop ) ; // Instantiate the date range.
if( ( dateRange.contains( today ) ) { // Call `LocalDateRange::contains` rather than write our own comparison logic.
Event event = … ;
events.add( event ) ;
} else {
// Skip this row. Does not meet our criterion of containing today's date.
}
}
Умные объекты, а не тупые нити
LocalDate rightNow = LocalDate.now();
String formatString = rightNow.format(DateTimeFormatter.ISO_LOCAL_DATE);
Почему вы генерируете строки? Я не вижу необходимости в строках, учитывая вашу проблему. При работе со значениями даты и времени используйте объекты даты и времени. Не используйте строки для бизнес-логики даты и времени.
Учебник
Совет. Прочитайте учебное пособие по java.time , предоставляемое Oracle бесплатно.