Мне нужно запросить данные за последний месяц из базы данных. Поэтому мне нужна первая и последняя дата предыдущего месяца, чтобы сделать SQL-запрос «между».
Конечно, первое свидание всегда начинается с 1, но жесткое кодирование выглядит плохо. Кроме того, жесткое кодирование формата даты «дд-мм-гггг» кажется плохой практикой. Есть ли более простой способ сделать это? Прямо сейчас у меня есть что-то любительское, но работающее, например:
YearMonth thisMonth = YearMonth.now();
YearMonth lastMonth = thisMonth.minusMonths(1);
String dd = Integer.toString(lastMonth.lengthOfMonth());
String mm = Integer.toString(lastMonth.getMonthValue());
String yyyy = Integer.toString(lastMonth.getYear());
String startDate = "01-" + mm + "-" + yyyy;
String endDate = dd + "-" + mm + "-" + yyyy;
System.out.println("startDate: " + startDate);
System.out.println("endDate: " + endDate);
@GMB Я использую оракул
Поэтому мне нужна первая и последняя дата предыдущего месяца, чтобы сделать SQL-запрос «между».
Вы можете сделать это вычисление прямо в своей базе данных. В Oracle вы можете получить первый и последний день предыдущего месяца в виде date
вот так:
where mydate between add_months(trunc(sysdate, 'month'), -1)
and last_day(add_months(trunc(sysdate, 'month'), -1))
В общем, between
и последний день особо не нужен. Можно использовать полуоткрытые интервалы — что также безопаснее, так как учитывает даты, относящиеся к последнему дню месяца:
where mydate >= add_months(trunc(sysdate, 'month'), -1)
and mydate < trunc(sysdate, 'month')
первый запрос дал 29.11. как последний день предыдущего месяца, но у меня сработал второй (30.11. был правильным). В любом случае мне все еще нужно преобразовать это в запрос JPA. Я сообщу, если у меня все получится, и приму это как ответ!
@виллбертос . . . Я исправил первый запрос. В исходном ответе не учитывались некоторые крайние случаи.
Не отправляйте первую и последнюю дату в виде строк в запрос к базе данных. Поскольку JDBC 4.2 передает LocalDate
объекты. Есть несколько способов выполнить вычисления в Java. Я бы предпочел использовать YearMonth
, как вы делаете в вопросе.
YearMonth thisMonth = YearMonth.now(ZoneId.of("Atlantic/Reykjavik"));
YearMonth lastMonth = thisMonth.minusMonths(1);
LocalDate startDate = lastMonth.atDay(1);
LocalDate endDate = lastMonth.atEndOfMonth();
System.out.println("startDate: " + startDate);
System.out.println("endDate: " + endDate);
Вывод при запуске сегодня:
startDate: 2020-11-01 endDate: 2020-11-30
Для перехода на JDBC:
String query = "select * from your_table where your_date_col between ? and ?;";
PreparedStatement statement = yourDatabaseConnection.prepareStatement(query);
statement.setObject(1, startDate);
statement.setObject(2, endDate);
В вашем распоряжении следующие регуляторы:
Демо:
import java.time.LocalDate;
import java.time.temporal.TemporalAdjusters;
class Main {
public static void main(String[] args) {
// Today's date
LocalDate today = LocalDate.now();
LocalDate oneMonthAgo = today.minusMonths(1);
LocalDate firstDateOfLastMonth = oneMonthAgo.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDateOfLastMonth = oneMonthAgo.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(firstDateOfLastMonth);
System.out.println(lastDateOfLastMonth);
}
}
Выход:
2020-11-01
2020-11-30
Узнайте больше о современном API даты и времени на Trail: Date Time.
String query = "SELECT column_name(s)
FROM table_name
WHERE column_name BETWEEN ? AND ?";
PreparedStatement st = conn.prepareStatement(query);
st.setObject(1, firstDateOfLastMonth);
st.setObject(2, lastDateOfLastMonth);
st.executeQuery();
//...Process ResultSet
st.close();
Это позволяет избежать жесткого кодирования 1
в соответствии с запросом. Хороший и рекомендуемый ответ.
Вы можете использовать TemporalAdjusters.firstDayOfMonth() и TemporalAdjusters.lastDayOfMonth()
См. документ: https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjusters.html#lastDayOfMonth--
LocalDate currentDate = LocalDate.now();
LocalDate currentDateLastMonth = LocalDate.of(
currentDate.getYear(),
currentDate.getMonth().minus(1),
currentDate.getDayOfMonth());
LocalDate firstDayOfMonth = currentDateLastMonth.with(TemporalAdjusters.firstDayOfMonth());
LocalDate lastDayOfMonth = currentDateLastMonth.with(TemporalAdjusters.lastDayOfMonth());
System.out.println("first day of the month "+ firstDayOfMonth);
System.out.println("last day of the month "+ lastDayOfMonth);
Вы можете сделать это вычисление непосредственно в своем запросе. Какую базу данных вы используете (mysql, oracle, sql-server...?), и как выглядит ваш запрос?