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

The above gives last working day of the current month. How can I get the last working day of the Previous month adjusting the above?

3
  • 3
    lastWorkingDayOfMonth = lastDayOfCurrentMonth.minusMonths(1); ??? This would get you the last day of the previous month, not the last working day. Do you mean to use minusDays(...) instead?
    – Thomas
    Commented Oct 2, 2017 at 14:56
  • 3
    As for the last working day of the previous month: once your code is fixed just feed lastDayOfCurrentMonth.minusMonths(1) to your switch statement, e.g. switch (lastDayOfCurrentMonth.minusMonths(1).getDayOfWeek() ) (note the method getDayOfWeek() which shortens the statement and thus increases readability tremendously).
    – Thomas
    Commented Oct 2, 2017 at 14:58
  • thanks - I see where it went wrong. I updated the lastDayOfCurrentMonth.minusMonths(1); to lastDayOfCurrentMonth.minusDays(1);
    – M06H
    Commented Oct 2, 2017 at 15:02

6 Answers 6

12

Another alternative is to use a java.time.YearMonth to get the previous month. Then you get the last day of this month and adjust to previous Friday if it's in a weekend:

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

Running this code today (October 2nd 2017), it gives lastDayPreviousMonth equals to 2017-09-29.


PS: You're using minusMonths in LocalDate instances, which wont' always work like you want. Example, if I have a date in February 2017:

// 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

The last day of February 2017 is 28th, and when calling minusMonths(1), you get the same day (28th) at the previous month (January), which is not what you want (the last working day in January 2017 is 31st).

Using YearMonth avoids this, because this class handles just the month and year, ignoring the day (so the minusMonths doesn't suffer such effects). So you can easily go to the desired month, and then you can correctly get the last day using the atEndOfMonth() method.

4

Sometimes, the simple approach is better than a clever approach:

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

You can change your switch statement with the following code:

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

Here, in this case I am calculating the last day of previous month (you can change the months before by changing the integer value in method minusMonths()'s parameter) with the weekends and in case of Weekends the Working day is changed accordingly.

4

tl;dr

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

previousWorkingDay

The ThreeTen-Extra project provides TemporalAdjuster implementations for finding the next/previous weekday (non-Saturday/Sunday).

The last day of the previous month may be the target, a weekday. So our strategy is to get the first day of this month, the look back to get first previous working day.

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

More simple and easy way without looping.

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

You can replace LocalDate.now().with(TemporalAdjusters.lastDayOfMonth()) in your code to LocalDate.now().minusMonth(1).with(TemporalAdjusters.lastDayOfMonth()) to get the last day of the previous month and after that keep on with the same logic to find the last working day of the month.

Not the answer you're looking for? Browse other questions tagged or ask your own question.