【问题标题】:last working day of previous month with LocalDateLocalDate 上个月的最后一个工作日
【发布时间】:2018-03-13 16:08:15
【问题描述】:
public static String getLastWorkingDayOfPreviousMonth() {

    LocalDate lastDayOfCurrentMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
    LocalDate lastWorkingDayOfMonth;

    switch (DayOfWeek.of(lastDayOfCurrentMonth.get(ChronoField.DAY_OF_WEEK))) {
        case SATURDAY:
            lastWorkingDayOfMonth = lastDayOfCurrentMonth.minusMonths(1);
            break;
        case SUNDAY:
            lastWorkingDayOfMonth = lastDayOfCurrentMonth.minusMonths(2);
            break;
        default:
            lastWorkingDayOfMonth = lastDayOfCurrentMonth;
    }

    return getFormattedDate(lastWorkingDayOfMonth);
}

上面给出了当月的最后一个工作日。如何获得Previous 月的最后一个工作日调整上述内容?

【问题讨论】:

  • lastWorkingDayOfMonth = lastDayOfCurrentMonth.minusMonths(1); ???这将使您获得上个月的最后一天,而不是最后一个工作日。您的意思是改用minusDays(...) 吗?
  • 至于上个月的最后一个工作日:一旦您的代码被修复,只需将 lastDayOfCurrentMonth.minusMonths(1) 输入到您的 switch 语句中,例如switch (lastDayOfCurrentMonth.minusMonths(1).getDayOfWeek() )(注意 getDayOfWeek() 方法,它缩短了语句,从而极大地提高了可读性)。
  • 谢谢 - 我知道哪里出了问题。我将lastDayOfCurrentMonth.minusMonths(1); 更新为lastDayOfCurrentMonth.minusDays(1);

标签: java date java-time localdate


【解决方案1】:

另一种方法是使用java.time.YearMonth 来获取上个月。然后你得到本月的最后一天,如果是周末,则调整到上周五:

LocalDate lastDayPreviousMonth = YearMonth
    // current year/month
    .now()
    // previous month
    .minusMonths(1)
    // last day of month
    .atEndOfMonth();
DayOfWeek dayOfWeek = lastDayPreviousMonth.getDayOfWeek();
// check if it's weekend
if (dayOfWeek == DayOfWeek.SATURDAY || dayOfWeek == DayOfWeek.SUNDAY) {
    // adjust to previous friday
    lastDayPreviousMonth = lastDayPreviousMonth.with(TemporalAdjusters.previous(DayOfWeek.FRIDAY));
}

今天(2017 年 10 月 2 日nd)运行此代码,它使 lastDayPreviousMonth 等于 2017-09-29


PS:你在LocalDate 实例中使用minusMonths,它不会总是像你想要的那样工作。例如,如果我的日期是 2017 年 2 月:

// Feb 15th 2017
LocalDate d = LocalDate.of(2017, 2, 15);
// adjust to last day of month (2017-02-28)
d = d.with(TemporalAdjusters.lastDayOfMonth());
System.out.println(d.minusMonths(1)); // 2017-01-28

2017 年 2 月的最后一天是 28th,当调用 minusMonths(1) 时,您会得到上个月(1 月)的同一天(28th) ,这不是你想要的(2017 年 1 月的最后一个工作日是 31st)。

使用YearMonth 可以避免这种情况,因为这个类只处理月份和年份,而忽略了日期(所以minusMonths 不会受到这种影响)。这样就可以很方便的去到想要的月份,然后就可以用atEndOfMonth()方法正确的得到最后一天了。

【讨论】:

    【解决方案2】:

    您可以使用以下代码更改您的 switch 语句:

    public static String getLastWorkingDayOfPreviousMonth() {
    
            LocalDate lastDayOfCurrentMonth = LocalDate.now().with(TemporalAdjusters.lastDayOfMonth());
            LocalDate lastWorkingDayOfMonth;
            switch (lastDayOfCurrentMonth.minusMonths(1).getDayOfWeek()) {
                case SATURDAY:
                    lastWorkingDayOfMonth = lastDayOfCurrentMonth.minusMonths(1).minusDays(1); // Here assgining second last day from previous month.
                    break;
                case SUNDAY:
                    lastWorkingDayOfMonth = lastDayOfCurrentMonth.minusMonths(1).minusDays(2); // Here assgining third last day from previous month.
                    break;
                default:
                    lastWorkingDayOfMonth = lastDayOfCurrentMonth.minusMonths(1); // Here assgining last day from previous month.
            }
    
            return lastWorkingDayOfMonth.toString();
        }
    

    在这里,在这种情况下,我正在计算上个月的最后一天(您可以通过更改方法 minusMonths() 的参数中的整数值来更改前几个月)和周末,如果是周末,工作日是相应地改变了。

    【讨论】:

      【解决方案3】:

      tl;博士

      LocalDate.now()
               .withDayOfMonth( 1 ) 
               .with( 
                   org.threeten.extra.Temporals.previousWorkingDay()
                )
      

      previousWorkingDay

      ThreeTen-Extra 项目提供 TemporalAdjuster 实现以查找 next/previous 工作日(非周六/周日)。

      上个月的最后一天可能是目标,即工作日。所以我们的策略是获取月的第一天,回溯以获取前一个工作日。

      ZoneId z = ZoneId.of( "America/Montreal" ) ; 
      LocalDate today = LocalDate.now( z );
      LocalDate firstOfMonth = today.withDayOfMonth( 1 ) ;
      LocalDate lastWorkingDayOfPreviousMonth = firstOfMonth.with( org.threeten.extra.Temporals.previousWorkingDay() ) ;
      

      【讨论】:

        【解决方案4】:

        有时,简单的方法比聪明的方法更好:

        LocalDate lastWorkingDayOfMonth = LocalDate.now().withDayOfMonth(1);
        do {
            lastWorkingDayOfMonth = lastWorkingDayOfMonth.minusDays(1);
        } while (lastWorkingDayOfMonth.getDayOfWeek() == DayOfWeek.SATURDAY ||
                 lastWorkingDayOfMonth.getDayOfWeek() == DayOfWeek.SUNDAY);
        

        【讨论】:

          【解决方案5】:

          没有循环的更简单和容易的方法。

          public static String getLastWorkingDayOfPreviousMonth() {
              LocalDate localDate = LocalDate.now().minusMonths(1).with(TemporalAdjusters.lastDayOfMonth());
              if (localDate.getDayOfWeek().getValue() > 5)
                  localDate = localDate.minusDays(localDate.getDayOfWeek().getValue() - 5);
              return getFormattedDate(localDate);
          }
          

          【讨论】:

            【解决方案6】:

            你可以替换LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()) 在您的代码中发送到LocalDate.now().minusMonth(1).with(TemporalAdjusters.lastDayOfMonth()) 以获取上个月的最后一天,然后继续使用相同的逻辑来查找该月的最后一个工作日。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2023-02-15
              • 2013-04-08
              • 1970-01-01
              • 2016-09-23
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2021-07-12
              相关资源
              最近更新 更多