Adding working days from a date in c#

Programmazione Microsoft Visual StudioAdding 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.