Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Find next 5 working days starting from today

Tags:

date

c#

I use nager.date to know if a day is a holiday day or a weekend day Saturday and Sunday).
I need to extract the date (starting from today or any other date) after 5 working days.

DateTime date1 = new DateTime(2019, 12, 23); 
int i = 0;
    
while ( i < 5)
{
   if (DateSystem.IsPublicHoliday(date1, CountryCode.IT) || DateSystem.IsWeekend(date1, CountryCode.IT))
   {
       date1 = date1.AddDays(1); 
   }
   else 
   {
       date1= date1.AddDays(1);
       i++;
   }
}

The problem of this code is that if the last else occurs, it add me 1 day but without doing any other check.

For example:
If the start date is 13/07/2020, the result will be at the end 18/07/2020 and as you can see is on Saturday.

How could I modify this code to achieve what I need?

like image 384
Andrea Calabrò Avatar asked Jul 16 '20 09:07

Andrea Calabrò


3 Answers

The order is important. The AddDays should be called first, and after it is called we check if the new day matches our criteria.

Note: I have renamed the i variable so it is more clear.

DateTime date1 = new DateTime(2019, 12, 23); 
int daysAdded = 0;

while (daysAdded < 5)
{
    date1 = date1.AddDays(1);
    if (!DateSystem.IsPublicHoliday(date1, CountryCode.IT) && !DateSystem.IsWeekend(date1, CountryCode.IT)) {
        // We only consider laboral days
        // laboral days: They are not holidays and are not weekends
        daysAdded ++;
    }
}
like image 151
Cleptus Avatar answered Sep 20 '22 15:09

Cleptus


I always try to generalize my solutions, so here's one enabling LINQ:

public bool IsWorkingDay(DateTime dt)
    => !DateSystem.IsPublicHoliday(dt) && !DateSystem.IsWeekend(dt);

public DateTime NextWorkingDay(DateTime dt)
{
    dt = dt.AddDays(1);
    while (!IsWorkingDay(dt))
        dt = dt.AddDays(1);
    return dt;
}

public IEnumerable<DateTime> WorkingDaysFrom(DateTime dt)
{
    if (!IsWorkingDay(dt))
        dt = NextWorkingDay(dt); // includes initial dt, remove if unwanted
    while (true)
    {
        yield return dt;
        dt = NextWorkingDay(dt);
    }
}

This will pump out working days from a given date until end of time, and then use LINQ to grab the number you want:

var next5 = WorkingDaysFrom(DateTime.Today).Take(5).ToList();

here's how to get all the working days in 2020:

var working2020 = WorkingDaysFrom(new DateTime(2020, 1, 1))
    .TakeWhile(dt => dt.Year == 2020)
    .ToList();
like image 31
Lasse V. Karlsen Avatar answered Sep 22 '22 15:09

Lasse V. Karlsen


DateTime date1 = new DateTime(2019, 12, 23); 
int i = 0;
while ( i < 5)
{
   date1 = date1.AddDays(1); 
   if (!DateSystem.IsPublicHoliday(date1, CountryCode.IT) && !DateSystem.IsWeekend(date1, CountryCode.IT)) 
    {           
        i++;
    }

}

but I think that you need a DateTime[] to store all the five days

like image 40
Francesco Avatar answered Sep 20 '22 15:09

Francesco