Blabberbox » 42 » Programming for HolidaysShare on Twitter

Programming for Holidays

April 12th, 2020 | Posted by pftq in 42 | #
In case anyone finds it useful, this is the code I use to automatically detect US holidays.  I don't claim credit for it - added bits and pieces over the years from various sources until it was complete enough that I didn't have to worry about it anymore.

Code:
       public bool isHoliday(DateTime date)
        {
            return GetHolidays(date.Year).Contains(date.Date);
        }

        public bool isHalfDay(DateTime date)
        {
            if (date.Month == 7 && date.Day == 3) return true;

            if (date.Month == 12 && date.Day == 24) return true;

            //if (date.Date == CalcGoodFri(date.Year).AddDays(-1)) return true;

            // Day after Thanksgiving
            var thanksgivingFriday = (from day in Enumerable.Range(1, 30)
                                where new DateTime(date.Year, 11, day).DayOfWeek == DayOfWeek.Friday
                                select day).ElementAt(3);
            DateTime thanksgivingFridayDate = new DateTime(date.Year, 11, thanksgivingFriday);
            if (date.Date == thanksgivingFridayDate) return true;

            return false;
        }

        private HashSet<DateTime> GetHolidays(int year)
        {
            HashSet<DateTime> holidays = new HashSet<DateTime>();

            // George W Bush
            if (year == 2018) holidays.Add(new DateTime(2018, 12, 5));

            // New Years
            DateTime newYearsDate = AdjustForWeekendHoliday(new DateTime(year, 1, 1));
            holidays.Add(newYearsDate);

            // MLK Day -- 3rd Monday in January
            var mlk = (from day in Enumerable.Range(1, 30)
                                where new DateTime(year, 1, day).DayOfWeek == DayOfWeek.Monday
                                select day).ElementAt(2);
            DateTime mlkDay = new DateTime(year, 1, mlk);
            holidays.Add(mlkDay);

            // President's Day -- 3rd Monday in January
            var pres = (from day in Enumerable.Range(1, 30)
                       where new DateTime(year, 2, day).DayOfWeek == DayOfWeek.Monday
                       select day).ElementAt(2);
            DateTime presDay = new DateTime(year, 2, pres);
            holidays.Add(presDay);

            // Good Friday
            holidays.Add(CalcGoodFri(year));

            // Memorial Day -- last monday in May
            DateTime memorialDay = new DateTime(year, 5, 31);
            DayOfWeek dayOfWeek = memorialDay.DayOfWeek;
            while (dayOfWeek != DayOfWeek.Monday)
            {
                memorialDay = memorialDay.AddDays(-1);
                dayOfWeek = memorialDay.DayOfWeek;
            }
            holidays.Add(memorialDay);

            // Independence Day
            DateTime independenceDay = AdjustForWeekendHoliday(new DateTime(year, 7, 4));
            holidays.Add(independenceDay);

            // Labor Day -- 1st Monday in September
            DateTime laborDay = new DateTime(year, 9, 1);
            dayOfWeek = laborDay.DayOfWeek;
            while(dayOfWeek != DayOfWeek.Monday)
            {
                laborDay = laborDay.AddDays(1);
                dayOfWeek = laborDay.DayOfWeek;
            }
            holidays.Add(laborDay);

            // Thanksgiving Day -- 4th Thursday in November
            var thanksgiving = (from day in Enumerable.Range(1, 30)
                           where new DateTime(year, 11, day).DayOfWeek == DayOfWeek.Thursday
                           select day).ElementAt(3);
            DateTime thanksgivingDay = new DateTime(year, 11, thanksgiving);
            holidays.Add(thanksgivingDay);

            // Christmas Day
            DateTime christmasDay = AdjustForWeekendHoliday(new DateTime(year, 12, 25));
            holidays.Add(christmasDay);

            // Next year's new years check
            DateTime nextYearNewYearsDate = AdjustForWeekendHoliday(new DateTime(year + 1, 1, 1));
            if (nextYearNewYearsDate.Year == year)
            holidays.Add(nextYearNewYearsDate);

            return holidays;
        }

        private DateTime AdjustForWeekendHoliday(DateTime holiday)
        {
            if (holiday.DayOfWeek == DayOfWeek.Saturday)
            {
                return holiday.AddDays(-1);
            }
            else if (holiday.DayOfWeek == DayOfWeek.Sunday)
            {
                return holiday.AddDays(1);
            }
            else
            {
                return holiday;
            }
        }

        // Credits to Mike Cook cited here: https://stackoverflow.com/questions/2510383/how-can-i-calculate-what-date-good-friday-falls-on-given-a-year
        private DateTime CalcGoodFri(int yr)
        {
            int a = yr % 19;
            int b = yr / 100;
            int c = yr % 100;
            int d = b / 4;
            int e = b % 4;
            int i = c / 4;
            int k = c % 4;
            int g = (8 * b + 13) / 25;
            int h = ((19 * a) + b - d - g + 15) % 30;
            int l = ((2 * e) + (2 * i) - k + 32 - h) % 7;
            int m = (a + (11 * h) + (19 * l)) / 433;
            int days_to_good_friday = h + l - (7 * m) - 2;
            int mo = (days_to_good_friday + 90) / 25;
            int da = (days_to_good_friday + (33 * mo) + 19) % 32;
            return new DateTime(yr, mo, da);
        }
Last Updated Nov 27th, 2020 | 339 unique view(s)

Leave a Comment

Name: (Have an account? Login or Register)
Email: (Won't be published)
Website: (Optional)
Comment:
Enter the code from image: