【问题标题】:How to add a number of days to a Date while skipping weekends and other holidays如何在跳过周末和其他假期的同时将天数添加到日期
【发布时间】:2011-12-28 08:33:16
【问题描述】:

给定一个日期。如何在跳过范围之间的周末和其他假期的同时添加天数?

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;
}

【问题讨论】:

  • 问题是..?你尝试了什么?
  • @user978511:我试过那个。但是我怎么能排除其他假期???
  • 那么你为什么不写下你尝试过的东西以及为什么它对你不起作用?
  • 给定的代码仅适用于周末...

标签: c# datetime c#-4.0 date


【解决方案1】:

要跳过假期,您首先需要创建自己的假期列表。每个国家/地区的假期都不同,并且受其他因素影响。

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

不幸的是,没有更简单的方法可以做到这一点。

【讨论】:

    【解决方案2】:

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

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

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

    请注意,这是假设开始日期不是周末/节假日。

    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;
    }
    

    【讨论】:

    • 您好 Elena,感谢您发布解决方案。对您的代码为何有效而其他代码无效的原因给出完整的解释是一个非常好的主意 - 这样人们就可以在家中学习一些东西。你能补充一下吗?
    • 已按要求编辑.. :)
    【解决方案3】:

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

        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
        }
    

    但如上所述,您需要运行自己的假期日历。

    【讨论】:

      【解决方案4】:
      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;
              }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-06-03
        • 1970-01-01
        • 1970-01-01
        • 2021-04-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多