Adding working days from a date in c#
Ovvero, vogliamo, a partire da una data, aggiungere un certo numero di ore e che si tenga conto dei giorni lavorativi.
AGGIORNAMENTI
20/12/2013 creazione articolo
Una funzione che può fare questo è la seguente:
Funzione che ad una data passata aggiunge x ore saltando il sabato e la domenica e le principali festività italiane.
Gli orari lavorativi sono considerati dalle 9 alle 18, dal lunedì al venerdì
public static class DateUtils
{
public static DateTime AddWorkingDay(DateTime startDate, int hours)
{
while(DateUtils.IsHoliday(startDate))
{
// Se è un giorno festivo si salta alle 9 del giorno successivo
startDate = startDate.AddHours(24);
startDate = new DateTime(startDate.Year, startDate.Month, startDate.Day, 9, 0, 0);
}
DateTime resultDate = startDate;
for (int i = 0; i < hours; i++)
{
resultDate = resultDate.AddHours(1);
// Se siamo alle 18 si passa alle 9 del giorno successivo
if (resultDate.Hour >= 18)
{
resultDate = resultDate.AddHours(24);
resultDate = new DateTime(resultDate.Year, resultDate.Month, resultDate.Day, 9, 0, 0);
}
while (DateUtils.IsHoliday(resultDate))
{
// Se è un giorno festivo si salta alle 9 del giorno successivo
resultDate = resultDate.AddHours(24);
resultDate = new DateTime(resultDate.Year, resultDate.Month, resultDate.Day, 9, 0, 0);
}
}
return resultDate;
}
private static bool IsHoliday(DateTime testDate)
{
//Festività standard
DateTime pasqua = DateUtils.Easter(testDate.Year);
DateTime lunediAngelo = pasqua.AddDays(1);
DateTime capodanno = new DateTime(testDate.Year, 1, 1);
DateTime epifania = new DateTime(testDate.Year, 1, 6);
DateTime liberazione = new DateTime(testDate.Year, 4, 25);
DateTime lavoratori = new DateTime(testDate.Year, 5, 1);
DateTime repubblica = new DateTime(testDate.Year, 6, 2);
DateTime ferragosto = new DateTime(testDate.Year, 8, 15);
DateTime ognissanti = new DateTime(testDate.Year, 11, 1);
DateTime immacolata = new DateTime(testDate.Year, 12, 8);
DateTime natale = new DateTime(testDate.Year, 12, 25);
DateTime santoStefano = new DateTime(testDate.Year, 12, 26);
LinkedList<DateTime> festivita = new LinkedList<DateTime>();
festivita.AddLast(pasqua);
festivita.AddLast(lunediAngelo);
festivita.AddLast(capodanno);
festivita.AddLast(epifania);
festivita.AddLast(liberazione);
festivita.AddLast(lavoratori);
festivita.AddLast(repubblica);
festivita.AddLast(ferragosto);
festivita.AddLast(ognissanti);
festivita.AddLast(immacolata);
festivita.AddLast(natale);
festivita.AddLast(santoStefano);
foreach (var festaTmp in festivita)
{
if (testDate.Month == festaTmp.Month && testDate.Day == festaTmp.Day && testDate.Year==festaTmp.Year)
return true;
}
if (testDate.DayOfWeek == DayOfWeek.Sunday ||
testDate.DayOfWeek == DayOfWeek.Saturday)
return true;
return false;
}
private static DateTime Easter(int year)
{
//Calcolo della Pasqua basato sul seguente algoritmo: http://www.assa.org.au/edm.html#Computer
int firstDigit;
int remain19;
int temp;
int tableA;
int tableB;
int tableC;
int tableD;
int tableE;
int d;
int m;
firstDigit = year / 100;
remain19 = year % 19;
temp = (firstDigit - 15) / 2 + 202 - 11 * remain19;
int[] substract1 = { 21, 24, 25, 27, 28, 29, 30, 31, 32, 34, 35, 38 };
List<int> subtract1List = new List<int>(substract1);
if (subtract1List.Contains(firstDigit))
{
temp = temp - 1;
}
int[] substract2 = { 33, 36, 37, 39, 40 };
List<int> subtract2List = new List<int>(substract2);
if (subtract2List.Contains(firstDigit))
{
temp = temp - 2;
}
temp = temp % 30;
tableA = temp + 21;
if (temp == 29)
{
tableA = tableA - 1;
}
if (temp == 28 && remain19 > 10)
{
tableA = tableA - 1;
}
tableB = (tableA - 19) % 7;
tableC = (40 - firstDigit) % 4;
if (tableC == 3)
{
tableC++;
}
if (tableC > 1)
{
tableC++;
}
temp = year % 100;
tableD = (temp + temp / 4) % 7;
tableE = ((20 - tableB - tableC - tableD) % 7) + 1;
d = tableA + tableE;
if (d > 31)
{
d = d - 31;
m = 4;
}
else
{
m = 3;
}
return new DateTime(year, m, d);
}
}
Questa funzione, alla data passata, aggiunge quindi un certo numero, sempre passato come argomento, di ore lavorative.
Si prenda in considerazione come assunto che si lavora dal lunedì al venerdì e dalle 9 alle 18.
Questa funzione è stata scritta in c#, ambiente quindi .NET e Microsoft Visual Studio 2010.