M06H
M06H

Reputation: 1773

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

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?

Upvotes: 5

Views: 10491

Answers (6)

MMZ2310
MMZ2310

Reputation: 11

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

Upvotes: 1

Basil Bourque
Basil Bourque

Reputation: 338211

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

Upvotes: 4

user7605325
user7605325

Reputation:

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.

Upvotes: 12

Ron Badur
Ron Badur

Reputation: 1963

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.

Upvotes: 0

Procrastinator
Procrastinator

Reputation: 2664

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.

Upvotes: 4

VGR
VGR

Reputation: 44293

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

Upvotes: 4

Related Questions