Использование приличном Date-Time Library
Вы должны избегать старых классов java.util.Date/.Calendar в комплекте с Java. Вместо этого используйте либо библиотеку Joda-Time, либо новую java.time package, встроенную в Java 8 и более позднюю версию (вдохновленную Joda-Time). Код ниже, используя Joda-Time 2.8, и будет очень похож, если вы используете java.time.
часового пояса
Временная зона имеет решающее значение при определении даты. Например, в Париже новый день наступает раньше, чем в Монреале. Большинство баз данных профессионального уровня хранят свои значения даты и времени в часовом поясе UTC. Вам необходимо настроить в соответствии с желаемым часовым поясом. Например, если «сегодня» в вашем приложении означает «сегодня в Монреале», тогда вы должны применить часовой пояс «Americal/Montreal».
Half-Open
Как правило, лучший способ обрабатывать диапазон даты и времени через подход "Half-Open". Это означает, что начало включительно в то время как окончание исключая. Это позволяет избежать таких проблем, как попытка определить последнюю дробную секунду дня. Поиск StackOverflow для обсуждения и другие примеры.
Дата-только
Возможно, вы используете совместимый тип java.sql.Date
данных (дату только значение, без времени в день) в базе данных, а не java.sql.Timestamp
-соместимым типа. Если это так, используйте класс LocalDate
в Joda-Time (или java.time).
Обработка значений даты и времени в MySQL очень ограничена, поэтому я не уверен, что этот пример кода будет работать там. Возможно, вам придется настроить. Этот пример был снят с моей реальной работы, используя Postgres, который имеет отличную обработку времени.
Преобразование java.util.Date
Если вам нужно преобразовать Joda-Time DateTime
к типу java.util.Date для взаимодействия, то простой вызов метода toDate
. Пакет java.time имеет похожие методы преобразования. Поиск StackOverflow.
PreparedStatement
Строго говоря, этот пример не нужно использовать PreparedStatement
. A PreparedStatement необходимо, если (a) вы будете называть это повторно и хотите повысить производительность, или (b) вам нужно избегать SQL injection рисков безопасности. Здесь тоже не так, но мне легче сделать привычку всегда использовать PreparedStatement
.
Код Пример
Следующий пример никогда не тестировался.
ArrayList<Person> list = new ArrayList<>(); // Goal is to populate this List with Person objects representing rows from the database.
// Purpose: Query database for "person_" rows where the person was born today.
DateTimeZone zone = DateTimeZone.forID("America/Montreal");
DateTime today = DateTime.now(zone); // Get the date-time for a particular time zone.
DateTime todayStart = today.withTimeAtStartOfDay(); // First moment of the day. Usually this is the time 00:00:00.000 but not always.
DateTime tomorrowStart = todayStart.plusDays(1);
// We will query by the "Half-Open" approach where the beginning is *inclusive* while the ending is *exclusive*.
java.sql.Timestamp tsStart = new java.sql.Timestamp(todayStart.getMillis()); // Convert a Joda-Time DateTime object to a java.sql.Timestamp object.
java.sql.Timestamp tsStop = new java.sql.Timestamp(tomorrowStart.getMillis());
StringBuilder sql = new StringBuilder();
sql.append("SELECT name_ , gender_ , date_of_birth_ " + "\n");
sql.append("FROM person_ " + "\n");
sql.append("WHERE date_of_birth_ >= ? AND date_of_birth_ < + ? " + "\n"); // Half-Open query, "[)", beginning is *inclusive* while the ending is *exclusive*.
sql.append(";");
try (Connection conn = DBHelper.instance().dataSource().getConnection() ; // Where "DBHelper" is your own class, to handle particulars for your own database, user account, password.
PreparedStatement pstmt = conn.prepareStatement(sql.toString()) ;) {
pstmt.setTimestamp(1, tsStart);
pstmt.setTimestamp(2, tsStop);
try (ResultSet rs = pstmt.executeQuery() ;) {
int count = 0; // Count rows extracted from ResultSet.
while (rs.next()) {
count++;
// Extract fields from this row.
String personName = rs.getString("name_");
String gender = rs.getString("gender_");
java.sql.Timestamp dateOfBirthTs = rs.getTimestamp("date_of_birth_");
DateTime dateOfBirth = new DateTime(dateOfBirthTs , zone);
// Instantiate an object to represent this row's data.
Person person = new Person(personName, gender, dateOfBirth); // Where "Person" is your own class for representing this data.
list.add(person); // Collect these Person objects.
}
// If expecting a certain number of rows, verify that number.
if (count == 0) {
logger.error("Found no row in database for date range: " + tsStart + "/" + tsStop + "."); // I recommend SLF4J & Logback as a logging solution.
} else if (count > 1) {
logger.error("Found more than a single row (" + count + ") in database for date range: " + tsStart + "/" + tsStop + ".");
}
}
} catch (SQLException ex) {
logger.error("SQLException during: " + message + "\n" + ex);
} catch (Exception ex) {
logger.error("Exception during: " + message + "\n" + ex);
}
Вы пытались это сделать? Если да, то можете ли вы показать, что сделали? Вы также упоминаете, что вы делаете это от JDBC - не могли бы вы показать нам свой код/фреймворк? – Sh4d0wsPlyr
'if (год и месяц рождения = год и месяц сегодняшнего дня) {born today} else {не родился сегодня}' –
Мне нужно будет постоянно меняться в моем коде. Но есть ли что-нибудь, что я могу изменить в своем заявлении sql, в котором, возможно, я использую временную метку? – johny