如何在跳过周末和其他假日的情况下为日期添加天数

本文关键字:情况下 日期 添加 假日 其他 周末 | 更新日期: 2023-09-27 18:18:59

给定日期。我如何添加天数,而跳过周末和其他假期之间的范围?

List <DateTime> holidays = new List<DateTime>()
{
     new DateTime(2012, 01, 03),
     new DateTime(2012, 01, 26)
}; 
dateTimeReview.Value = CalculateFutureDate(dateTimeStart.Value, 7,holidays);
static DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
     var futureDate = fromDate;
     for (var i = 0; i < numberofWorkDays; i++ )
     {
          if (futureDate.DayOfWeek == DayOfWeek.Saturday 
             || futureDate.DayOfWeek == DayOfWeek.Sunday
             || (holidays != null && holidays.Contains(futureDate)))
          {
              futureDate = futureDate.AddDays(1); // Increase FutureDate by one because of condition
              futureDate = futureDate.AddDays(1); // Add a working day
          }
     }
     return futureDate;
}

如何在跳过周末和其他假日的情况下为日期添加天数

要跳过假期,首先需要创建自己的假期列表。每个国家的假期都不一样,而且还受其他因素的影响。

然后,您应该在循环中逐个添加天数,并检查添加的天数是否不是周末,是否出现在假日列表中,直到添加给定的天数为止。

我尝试了上面的代码,但没有工作。返回的日期将以某种方式包括假日和周末。我还想检查返回的日期是否仅在工作日。

所以,下面是我修改的代码。

基本上,它将计算要添加的工作日数,如果结束日期是假日/周末,则将日期移到第二天。

请注意,这是在假设开始日期不是周末/节假日的情况下。

static DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays,   
                                    ICollection<DateTime> holidays)
{
     var futureDate = fromDate;
     for (var i = 0; i < numberofWorkDays; i++ )
     {
          if (futureDate.DayOfWeek == DayOfWeek.Saturday 
             || futureDate.DayOfWeek == DayOfWeek.Sunday
             || (holidays != null && holidays.Contains(futureDate)))
          {
              futureDate = futureDate.AddDays(1);
              numberofWorkDays++;
          }
          else
          {
              futureDate = futureDate.AddDays(1);
          }
     }
     while(futureDate.DayOfWeek == DayOfWeek.Saturday 
             || futureDate.DayOfWeek == DayOfWeek.Sunday
             || (holidays != null && holidays.Contains(futureDate)))
     {
          futureDate = futureDate.AddDays(1);
     }
     return futureDate;
}

我已经构建了一个类似的东西来检查办公时间:

    public static DateTime AddBusinessHours(DateTime date, long hours)
    {
        int i = 0;
        DateTime tmpDate = date;
        do
        {
            tmpDate = tmpDate.AddHours(1);
            if (!IsWeekend(tmpDate) && !IsHoliday(tmpDate) && IsOfficeHours(tmpDate))
                i++;
        }
        while (i < hours);
        return tmpDate;
    }

    public static bool IsWeekend(DateTime date)
    {
        return (date.DayOfWeek == DayOfWeek.Saturday || date.DayOfWeek == DayOfWeek.Sunday);
    }

    public static bool IsHoliday(DateTime date)
    {
        //All dates in the holiday calendar are without hours and minutes.
        //With the normal date object, the Contains does not work.
        DateTime tmp = new DateTime(date.Year, date.Month, date.Day); 
        HolidayCalendar calendar = HolidayCalendar.Instance;
        return (calendar.Dates.Contains(tmp));
    }

    public static bool IsOfficeHours(DateTime date)
    {
        return (date.Hour >= 8 && date.Hour < 20);   //Office Hours are between 8AM and 8PM
    }

但是正如上面提到的,你需要运行你自己的节日日历。

public static DateTime AddBusinessDays(DateTime pActualDate, int pNumberofWorkDays)
        {
            ICollection<DateTime> holidays = GetAllHolidays();
            int i = default(int);
            while (i < pNumberofWorkDays)
            {
                pActualDate = pActualDate.AddDays(1);
                if (pActualDate.DayOfWeek == DayOfWeek.Saturday || pActualDate.DayOfWeek == DayOfWeek.Sunday
                    || (holidays != null && holidays.Contains(pActualDate))) { }
                else
                { i++; }
            }
            return pActualDate;
        }

private static ICollection<DateTime> GetAllHolidays()
        {
            ICollection<DateTime> holidays = GetPublicHolidays().Select(s => s.Holidays).ToList();
            HashSet<DateTime> finalHolidays = new HashSet<DateTime>();
            //if sunday holiday then the following monday will be holiday
            bool isMonday = GetCalendar().Any(s => s.Type == "KR" && s.IsMonday);
            foreach (var hol in holidays)
            {
                if (hol.DayOfWeek == DayOfWeek.Sunday && isMonday)
                {
                    //adding monday following day holiday to the list
                    finalHolidays.Add(hol.AddDays(1));
                }
            }
            //exclude weekends from the holiday list
            var excludeWeekends = holidays.Where(s => s.DayOfWeek == DayOfWeek.Sunday || s.DayOfWeek == DayOfWeek.Saturday);
            //adding monday to the existing holiday collection
            finalHolidays.UnionWith(holidays.Except(excludeWeekends));
            return finalHolidays;
        }