Search code examples
javadatedatetimegregorian-calendarlocaldate

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


Solution

  • 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.