M06H
M06H

Reputation: 1783

last working date that is not holiday

I have the following Holiday class:

public class Holiday {

    private int day;
    private int month;


    public Holiday(GregorianCalendar calendar) {
        this.day = calendar.get(GregorianCalendar.DAY_OF_MONTH);
        this.month = calendar.get(GregorianCalendar.MONTH) + 1;
    }

}

enum Day:

public enum Day {

    SATURDAY(6), SUNDAY(7);

    private int index;

    Day(int index) {
        this.index = index;
    }

    public int getIndex() {
        return index;
    }
}


public class DateTool {

    private static final String DATE_FORMAT = "yyyy_MM_dd";

    public DateTool() {
        super();
    }


    public static String getPreviousWorkingDay(List<Holiday> listOfHolidays) {
            //derive the last working day that is not saturday/sunday
    }

    public static String parseDate(Date date) {
        return new SimpleDateFormat(DATE_FORMAT).format(date);
    }

    public static boolean isSunday(LocalDateTime date) {
        return date.getDayOfWeek().getValue() == Day.SUNDAY.getIndex();
    }

    public static boolean isSaturday(LocalDateTime date) {
        return date.getDayOfWeek().getValue() == Day.SATURDAY.getIndex();
    }

}

Given I have list of holidays, how can I work out and return the last previous working day in getPreviousWorkingDay(...) method which will exclude saturday and sunday?

I am trying to derive the last file date to look for so something like this I am trying to work out

  if (todayIsHoliday(listOfHolidays)) {
                getPreviousWorkingDay(listOfHolidays);
            }

so If current day is holiday, look at the last date which is not holiday and return as string formatted.

I’m unsure as to how to look back. Please note list of holidays is not only Saturday and Sunday. They are country holidays e.g Chinese New Year etc.

I’m using java 8 for this so any refactorings or improvements is welcome :)

Upvotes: 2

Views: 2098

Answers (2)

Basil Bourque
Basil Bourque

Reputation: 338604

The Answer by Ole V.V. is good. Here’s a couple more tips to augment that approach.

EnumSet

You can define your weekend as a EnumSet of DayOfWeek objects for Saturday and Sunday. An EnumSet is a highly efficient implementation of Set for holding enum objects. Takes very little memory, and has very fast execution.

Set<DayOfWeek> weekend = EnumSet.of( DayOfWeek.SATURDAY , DayOfWeek.SUNDAY ) ;

Then ask if a date’s day-of-week is contained in that set.

boolean isWeekend = weekend.contains( localDate.getDayOfWeek() ) ;

ThreeTen-Extra

The ThreeTen-Extra project extends the java.time with additional features. Among this features is a TemporalAdjuster for moving to the next/previous date while skipping any Saturday or Sunday.

LocalDate nextWeekDay = org.threeten.extra.Temporals.nextWorkingDay( localDate ) ;

Custom TemporalAdjuster

You can write your own implementation of TemporalAdjuster to encapsulate all your weekend + holiday logic in one place that can be easily reused with a simple compact call.

LocalDate nextBusinessDay = localDate.with( com.example.Temporals.nextBusinessDay() ) ;

Upvotes: 3

Anonymous
Anonymous

Reputation: 86276

private static final DateTimeFormatter dateFormatter
        = DateTimeFormatter.ofPattern("uuuu_MM_dd");

public static String getPreviousWorkingDay(List<MonthDay> listOfHolidays) {
    LocalDate workingDay = LocalDate.now(ZoneId.of("Pacific/Easter")).minusDays(1);
    while (workingDay.getDayOfWeek().equals(DayOfWeek.SATURDAY) 
            || workingDay.getDayOfWeek().equals(DayOfWeek.SUNDAY)
            || listOfHolidays.contains(MonthDay.from(workingDay))) {
        workingDay = workingDay.minusDays(1);
    }
    return workingDay.format(dateFormatter);
}

I am using java.time, the modern Java date and time API, and as mentioned in a comment I recommend you do the same. Let’s see the above method in action:

    System.out.println(getPreviousWorkingDay(Collections.emptyList()));
    // Let’s say Valentin’s day is a holiday
    System.out.println(getPreviousWorkingDay(List.of(MonthDay.of(Month.FEBRUARY, 14))));
    // And so are Lent Monday and the death day of Danish would-be king Henrik 
    System.out.println(getPreviousWorkingDay(List.of(MonthDay.of(Month.FEBRUARY, 12), 
            MonthDay.of(Month.FEBRUARY, 13), MonthDay.of(Month.FEBRUARY, 14))));

Today this printed:

2018_02_14
2018_02_13
2018_02_09

(I am cheating a bit since Lent Monday is not the same day every year; but I figure it’s not a requirement to take such holidays into account.)

Since determining today’s date is a time zone sensitive operation, please substitute your desired time zone if it didn’t happen to be the Easter Island time zone. Edit: In Java 8 use Arrays.asList() instead of the Java 9 List.of().

Link: Oracle tutorial: Date Time explaining how to use java.time.

Upvotes: 4

Related Questions