【问题标题】:Last date of next month in JavaJava中下个月的最后一个日期
【发布时间】:2019-11-27 09:03:04
【问题描述】:

如何在 Java 中获取下个月的最后一个日期?

背景:我有项目,用户只对订单感兴趣,应该在下个月底完成。所以我需要获取下个月的最后一个日期并与订单结束日期进行比较,如果订单结束日期小于下个月的最后一个日期,则意味着应该选择该订单。

我的解决方案是这样的,但不确定是不是最好的:

public static boolean shouldCompleteByNextMonth(final Date endDate) {
    final LocalDate now = LocalDate.now(); // Get current local date. 
    final LocalDate nextMonth = now.plusMonths(1); // Get next month.
    final int daysInNextMonth = nextMonth.lengthOfMonth(); // Get the length of next month
    final LocalDate lastLocalDateOfNextMonth = nextMonth.plusDays(daysInNextMonth - now.getDayOfMonth());  // Get the last Date of next month

    // default time zone
    final ZoneId defaultZoneId = ZoneId.systemDefault();

    // convert last locale date to a Date
    final Date lastDateOfNextMonth = Date.from(lastLocalDateOfNextMonth.atStartOfDay(defaultZoneId).toInstant());

    // Compare with the given endDate, if last date of next month is after it, return true, else, return false.
    return lastDateOfNextMonth.after(endDate);
}

【问题讨论】:

  • 最好给出自己的解决方案,这样我们就可以讨论它而不是寻求解决方案。我建议关闭此问题,因为idownvotedbecau.se/noattempt
  • 得到两个月的第一个然后减去一天会更简单吗?

标签: java date localdate


【解决方案1】:

TemporalAdjusters 类包含一些静态的TemporalAdjusters,其中有lastDayOfMonth(),所以你可以这样做

LocalDate.now()
         .plusMonth(1)
         .with(TemporalAdjusters.lastDayOfMonth());

【讨论】:

    【解决方案2】:

    在那之后计算一个月的第一天然后减去一天似乎更容易......

    LocalDate targetDate = LocalDate.now()
                                    .withDayOfMonth(1)
                                    .plusMonths(2)
                                    .minusDays(1);
    

    【讨论】:

      【解决方案3】:

      tl;博士

      YearMonth
      .now( 
          ZoneId.of( "Africa/Tunis" )
      )
      .plusMonths( 1 ) 
      .atEndOfMonth()
      

      返回LocalDate

      .toString(): 2019-12-31

      但是……最好使用半开方法而不是每月的最后一天。

      YearMonth

      YearMonth 类代表整个月份。

      ZoneId z = ZoneId.of( "America/Montreal" ) ;
      YearMonth nextMonth = YearMonth.now( z ).plusMonths( 1 ) ;
      

      注意时区的使用,ZoneId。对于任何给定的时刻,日期在全球范围内因区域而异。例如,日本东京 11 月 30 日午夜过后的几分钟是新的一个月,而在美国俄亥俄州托莱多仍然是“上个月”。因此,如果在运行时当前时刻位于该月的第一天或最后一天,则需要时区来确定当前月份的准确性。

      要求每月最后一天的LocalDate

      LocalDate lastDayOfMonth = nextMonth.atEndOfMonth() ; 
      

      半开

      对抗时间跨度通常采用的方法是半开放式方法。开头是inclusive,而结尾是exclusive

      这意味着一天从一天的第一刻开始(通常是 00:00,但并非总是如此),一直持续到但不包括下一天的第一刻 .

      在您的情况下,一个月从第一个月开始,一直持续到(但确实包括)下个月的第一个月。

      半开放式方法允许时间跨度几乎彼此无间隙地相邻。

      您的搜索条件逻辑应该是查找订单等于或大于 大于一个月的第一天并且 小于 下一个月的第一天的订单。在 Java 中,这将是 >= && <

      该逻辑的一种更简单的形式是查找订单日期不早于月初且*早于** 下个月的第一天的订单。

      ZoneId z = ZoneId.of( "America/Montreal" ) ;
      YearMonth nextMonth = YearMonth.now( z ).plusMonths( 1 ) ;
      LocalDate start = nextMonth.atDay( 1 ) ;
      LocalDate stop = nextMonth.plusMonths( 1 ).atDay( 1 ) ;
      

      LocalDateRange

      ThreeTen-Extra 库添加到您的项目中,以从 LocalDateRange 中受益。此类将时间跨度表示为一对LocalDate 对象。它提供了方便的比较方法,例如abutscontains

      LocalDateRange nextMonthRange = 
          LocalDateRange.of(
              nextMonth.atDay( 1 ) ,
              nextMonth.plusMonths( 1 ).atDay( 1 )
          ) 
      ;
      

      数据库

      您在问题中提到了一个数据库。

      这里是一个粗略的示例 JDBC 代码,用于查询下个月的订单。即,到期日在下个月的下个月的第一天之前的订单。

      请注意我们如何将 两个 个月添加到当前月份,以获得下个月的下个月。

      SQL 的关键部分是:WHERE due_date_ < ? 用于对运行到但的日期的半开查询,包括经过的日期(下个月的第一个月)。

      ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
      LocalDate firstOfMonthAfterNextMonth = YearMonth.now( z ).plusMonths( 2 ).atDay( 1 ) ;
      
      String sql = "SELECT order_number_ FROM order_ WHERE due_date_ < ? ; " ;
      try(
          Connection conn = myDataSource.getConnection() ;
          PreparedStatement ps = conn.prepareStatement( sql ) ;
      )
      {
          ps.setObject( 1 ; firstOfMonthAfterNextMonth ) ;
          try(
              ResultSet rs = ps.executeQuery() ;
          )
          {
              while ( rs.next() ) {
                  …
              }
          }
      } catch ( SQLException e ) {
          e.printStackTrace();
          … 
      } catch ( SQLTimeoutException  e ) {
          e.printStackTrace();
          …
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-05-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-02-08
        • 1970-01-01
        • 2021-06-07
        • 1970-01-01
        相关资源
        最近更新 更多