Sprawdzanie wolnych dni od pracy C#

By | 20 kwietnia 2016

Niemalże we wszystkich programach zarządzających pracownikami niezbędny jest algorytm sprawdzania czy w danym dniu jest dzień wolny, a co za tym idzie, można bardzo prosto wyliczyć ile dni pracujących było w określonym przedziale czasowym. Przydaje się to np. w trakcie wyliczania ilości pozostałego urlopu, ponieważ do urlopu nie wliczają się soboty, niedziele i święta.

Korzystając z zasobów internetu znalazłem i usprawniłem algorytm przeliczający święta aktualny dla daty publikacji tego artykułu (oczywiście po wprowadzeniu lub likwidacji jakiegoś święta w późniejszym terminie stanie się nieaktualny). Algorytm działa w przedziale od 1900 roku do aktualnej daty (o ile od 2016 nie zmieniono jakiegoś święta).

Funkcja IsDayOff zwraca true w przypadku, gdy podany dzień jest dniem wolnym, a false gdy nie jest wolny.

Funkcja GetNearestPreviousWorkDay zwraca najbliższy poprzedni dzień, który nie jest wolny od pracy.

Funkcja GetNearestNextWorkDay w przeciwieństwie do powyższej zwraca następny dzień, który nie jest wolny od pracy.

    public static class DayOffCalculator
    {
        public static bool IsDayOff(DateTime date)
        {
            if (date.DayOfWeek == DayOfWeek.Saturday) return true;
            if (date.DayOfWeek == DayOfWeek.Sunday) return true;
            if (date.Month == 01 && date.Day == 01) return true; // Nowy Rok
            if (date.Month == 01 && date.Day == 01 && (date.Year >= 1952 && date.Year <= 1960)) return true; // Trzech Króli if (date.Month == 05 && date.Day == 01) return true; // 1 maja if (date.Month == 05 && date.Day == 03 && (date.Year >= 1918 && date.Year <= 1950 || date.Year >= 1990)) return true; // 3 maja
            if (date.Month == 07 && date.Day == 22 && (date.Year >= 1945 && date.Year <= 1989)) return true; // Narodowe Święto Odrodzenia Polski
            if (date.Month == 08 && date.Day == 15 && (date.Year <= 1960 || date.Year >= 1989)) return true; // Wniebowzięcie Najświętszej Marii Panny, Święto Wojska Polskiego (rocznica “cudu nad Wisłą”)
            if (date.Month == 11 && date.Day == 01) return true; // Dzień Wszystkich Świętych
            if (date.Month == 11 && date.Day == 11 && (date.Year == 1937 || date.Year == 1938 || date.Year >= 1990)) return true; // Dzień Niepodległości 
            if (date.Month == 12 && date.Day == 25) return true; // Boże Narodzenie
            if (date.Month == 12 && date.Day == 26) return true; // Boże Narodzenie
            int a = date.Year % 19;
            int b = date.Year % 4;
            int c = date.Year % 7;
            int d = (a * 19 + 24) % 30;
            int e = (2 * b + 4 * c + 6 * d + 5) % 7;
            if (d == 29 && e == 6) d -= 7;
            if (d == 28 && e == 6 && a > 10) d -= 7;
            DateTime Easter = new DateTime(date.Year, 3, 22).AddDays(d + e);
            if (date.AddDays(-1) == Easter) return true; // Wielkanoc (poniedziałek)
            if (date.AddDays(-60) == Easter) return true; // Boże Ciało
            return false;
        }

        public static DateTime GetNearestPreviousWorkDay(DateTime changeDate)
        {
            for (int i = 0; i < 14; i++)
            {
                if (DayOffCalculator.IsDayOff(changeDate))
                {
                    changeDate = changeDate.AddDays(-1);
                }
                else
                {
                    break;
                }
            }
            return changeDate;
        }

        public static DateTime GetNearestNextWorkDay(DateTime changeDate)
        {
            for (int i = 0; i < 14; i++)
            {
                if (DayOffCalculator.IsDayOff(changeDate))
                {
                    changeDate = changeDate.AddDays(1);
                }
                else
                {
                    break;
                }
            }
            return changeDate;
        }
    }

Kod jest na tyle prosty, że w bardzo łatwy sposób można go przenieść na język C++ lub Javę zmieniając bardzo niewiele parametrów. Czekam na komentarze, jeśli jeżeli o jakimś święcie zapomniałem i nie ująłem w kodzie.

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *