【问题标题】:Get previous months first and last date获取前几个月的第一个和最后一个日期
【发布时间】:2021-03-22 18:10:59
【问题描述】:

我需要从数据库中查询上个月的数据。所以我需要上个月的第一个和最后一个日期才能进行“介于”SQL 查询。

当然,第一次约会总是从 1 开始,但硬编码看起来很糟糕。此外,硬编码 日期格式 "dd-MM-yyyy" 似乎是一种不好的做法。 有没有更简单的方法来做到这一点?现在我有一些业余但工作的东西,就像这样:

        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);

【问题讨论】:

  • 您可以直接在查询中进行计算。您正在运行哪个数据库(mysql、oracle、sql-server...?),您的查询是什么样的?
  • @GMB 我正在使用 oracle

标签: java sql oracle datetime where-clause


【解决方案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);

【讨论】:

    【解决方案2】:

    以下调整器随时为您服务:

    1. TemporalAdjusters.firstDayOfMonth()

    2. TemporalAdjusters.lastDayOfMonth()

    演示:

    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
    

    通过 Trail: Date Time 了解有关现代日期时间 API 的更多信息。

    如何在 JDBC 4.2 中使用 Java 8 Date and Time API (JSR-310):

    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 所要求的。一个很好的推荐答案。
    【解决方案3】:

    将 LocalDate 对象传输到您的 SQL 查询

    不要将第一个和最后一个日期作为字符串发送到数据库查询。从 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);
    

    【讨论】:

      【解决方案4】:

      所以我需要上个月的第一个和最后一个日期才能进行“介于”SQL 查询。

      您可以直接在数据库中进行计算。在 Oracle 中,您可以获得上个月的第一天和最后一天为 dates,如下所示:

      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 查询。如果我得到它的工作,我会报告并接受这个作为答案!
      • @willberthos 。 . .我修复了第一个查询。最初的答案没有考虑到一些边缘情况。
      猜你喜欢
      • 2012-05-29
      • 2013-06-23
      • 1970-01-01
      • 1970-01-01
      • 2013-02-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多