LocalDate 上个月的最后一个工作日

last working day of previous month with LocalDate

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 月的最后一个工作日来调整上述内容?

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

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

您可以使用以下代码更改您的 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() 的参数中的整数值来更改之前的月份)和周末,如果是周末工作日相应更改。

另一种方法是使用 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));
}

运行 这个代码今天(10 月 2nd 2017),它给出 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) 时,您得到的是同一天(28th) 上个月(1月),这不是你想要的(2017年1月的最后一个工作日是31st)。

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

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

tl;博士

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

previousWorkingDay

ThreeTen-Extra project provides TemporalAdjuster implementations for finding the next/previous 工作日 (non-Saturday/Sunday)。

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

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

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

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