tl; dr
Использование подхода Half-Open, логика >= AND <
, для промежутка времени, никогда BETWEEN
.
Неправильная логика
время начала -> октябрь 14 22:00 время окончания -> окт 14 14:00 ... тогда я должен все строки, время начала которых больше моего переданного значения ивремя окончания меньше моего переданного значения
Эта логика неверна.Делая такие почасовые отчеты с такой логикой, Вы никогда не будете сообщать об элементах, которые были зарегистрированы, когда часы бьют час.Строки со значением прямо в 10:00 точно (10: 00: 00.0) или 11:00 точно (11: 00: 00.0) никогда не будут найдены.
Half-Open
Я предлагаю последовательно использовать подход Half-Open для определения промежутка времени.В этом подходе начало включительно , а окончание исключительно .Например, час начинается с первого момента 10:00 и продолжается, но не включает время, когда часы бьют 11:00.
При таком подходе я получу серию почасовых запросов, чтобы найти все строки.Строки не исчезнут, как в вашей логике.
SELECT *
FROM event_
WHERE when_ >= ?
AND when_ < ?
;
Другими словами, никогда не используйте BETWEEN
с промежутком времени.Вместо этого используйте >= AND <
логику.
Часовой пояс
Вопрос о часовом поясе имеет решающее значение, если говорить о реальных моментах, если говорить о стандартном столбце SQL типа TIMESTAMP WITH TIME ZONE
.
В вашем примереВы имеете в виду 10 утра в Париже, Франция?Или в 10 утра в Монреале-Квебеке, несколько часов спустя?Или в 10 часов утра в Калькутте, Индия, несколькими часами ранее?
В Java задайте критерии как моменты, используя часовой пояс с классом ZonedDateTime
.
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
LocalDate ld = LocalDate.of( 2018 , 10 , 14 ) ;
LocalTime lt = LocalTime.of( 10 , 0 ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;
Чтобы просмотреть тот же момент в UTC, извлеките Instant
.
Instant instant = zdt.toInstant() ;
Создание текста, представляющего его значение в стандартном формате ISO 8601.
String output = instant.toString() ; // Generate text in standard ISO 8601 format.
Передайте это SQL-запросу в подготовленном операторе, используя драйвер JDBC, совместимый с JDBC 4.2 или новее.
myPreparedStatement.setObject( 1 , zdtStart ) ;
myPreparedStatement.setObject( 2 , zdtStop ) ;
О java.time
Среда java.time встроена в Java 8и позже.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date
, Calendar
, & SimpleDateFormat
.
Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на классы java.time .
Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .
Вы можете обмениваться java.time объектами непосредственно с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.*
классах.
Где получить классы java.time?
Проект ThreeTen-Extra расширяет java.time дополнительными классами.Этот проект является полигоном для возможных будущих дополнений к java.time.Здесь вы можете найти некоторые полезные классы, такие как Interval
, YearWeek
, YearQuarter
и more .