// Copyright (C) 2010 Aleksandr Dobkin, Michael Choi, and Christopher Mills.
//
// This file is part of BusRadar <https://github.com/orgs/busradar/>.
//
// BusRadar is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 3 of the License, or
// (at your option) any later version.
//
// BusRadar is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
package busradar.madison;
import java.util.Calendar;
import java.util.GregorianCalendar;
import static java.util.Calendar.*;
public class HolidayChecker {
private static void
shift_to_nearest_weekday(Calendar day)
{
int day_of_week = day.get(DAY_OF_WEEK);
if (day_of_week == SATURDAY)
day.add(DAY_OF_MONTH, -1);
else if (day_of_week == SUNDAY)
day.add(DAY_OF_MONTH, 1);
}
private static boolean
same_date(Calendar c1, Calendar c2)
{
return (c1.get(YEAR) == c2.get(YEAR) &&
c1.get(DAY_OF_YEAR) == c2.get(DAY_OF_YEAR));
}
private static void
shift_to_nth_day_of_month(GregorianCalendar cal, int month, int day_of_week, int n)
{
cal.set(MONTH, month);
cal.set(DAY_OF_MONTH, 1);
int now = cal.get(DAY_OF_WEEK);
int shift = 0;
if (now > day_of_week)
shift = 7 - (now - day_of_week);
else if (now < day_of_week)
shift = day_of_week - now;
shift += 7 * n;
cal.add(DAY_OF_MONTH, shift);
}
private static void
shift_to_date(GregorianCalendar cal, int month, int day)
{
cal.set(MONTH, month);
cal.set(DAY_OF_MONTH, day);
}
private static boolean
check_numbered_date(GregorianCalendar date, int month, int day_of_month, boolean shift_to_weekday)
{
GregorianCalendar holiday = (GregorianCalendar)(date.clone());
shift_to_date(holiday, month, day_of_month);
if (shift_to_weekday)
shift_to_nearest_weekday(holiday);
return same_date(date, holiday);
}
private static boolean
check_named_date(GregorianCalendar date, int month, int day_of_week, int num_weeks)
{
GregorianCalendar holiday = (GregorianCalendar)(date.clone());
shift_to_nth_day_of_month(holiday, month, day_of_week, num_weeks);
return same_date(date, holiday);
}
// New Year's Day
// January 1
public static boolean
New_Years_Day_Observed(GregorianCalendar day)
{
GregorianCalendar holiday1 = (GregorianCalendar)(day.clone());
GregorianCalendar holiday2 = (GregorianCalendar)(day.clone());
holiday1.set(DAY_OF_YEAR, 1);
holiday2.set(DAY_OF_YEAR, 1);
holiday2.add(YEAR, 1);
shift_to_nearest_weekday(holiday1);
shift_to_nearest_weekday(holiday2);
return (same_date(day, holiday1) || same_date(day, holiday2));
}
// Martin Luther King, Jr. Day
// Third Monday in January
public static boolean
Martin_Luther_King_Day(GregorianCalendar day)
{
return check_named_date(day, JANUARY, MONDAY, 2);
}
// Memorial Day
// Last Monday in May
public static boolean
Memorial_Day(GregorianCalendar day)
{
return check_named_date(day, MAY+1, MONDAY, -1);
}
// Independence Day
// July 4
public static boolean
Independence_Day_Observed(GregorianCalendar day)
{
return check_numbered_date(day, JULY, 4, true);
}
// Labor Day
// First Monday in September
public static boolean
Labor_Day(GregorianCalendar day)
{
return check_named_date(day, SEPTEMBER, MONDAY, 0);
}
// Thanksgiving Day
// Fourth Thursday in November
public static boolean
Thanksgiving_Day(GregorianCalendar day)
{
return check_named_date(day, NOVEMBER, THURSDAY, 3);
}
//Thanksgiving Day
//Fourth Thursday in November
public static boolean
Thanksgiving_Day_After(GregorianCalendar day)
{
GregorianCalendar holiday = (GregorianCalendar)(day.clone());
shift_to_nth_day_of_month(holiday, NOVEMBER, THURSDAY, 3);
holiday.add(DAY_OF_MONTH, 1);
return same_date(day, holiday);
}
// Christmas Day
// December 25
public static boolean
Christmas_Day_Observed(GregorianCalendar day)
{
return check_numbered_date(day, DECEMBER, 25, true);
}
}