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.

[csharp]
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;
}
}
[/csharp]

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 *