【问题标题】:Count days worked in a week without looping?计算一周内没有循环的工作天数?
【发布时间】:2011-06-16 15:47:19
【问题描述】:

我需要计算给定结构的总工作天数,该结构表示一周中的哪几天工作以及从开始到现在。

我目前的算法是这样的:

protected int TotalWorkDays(DateTime From, DateTime dtTo,WorkedDays days)
    {
        int Days = 0;
        DayOfWeek DOW;
        for (DateTime curDate = From; curDate.Date <= dtTo.Date; curDate = curDate.AddDays(1))
        {
            DOW = curDate.DayOfWeek;
            if ((DOW == DayOfWeek.Sunday &  days.Sunday) |
                (DOW == DayOfWeek.Monday &  days.Monday) |
                (DOW == DayOfWeek.Tuesday &  days.Tuesday) |
                (DOW == DayOfWeek.Wednesday &  days.Wednesday) |
                (DOW == DayOfWeek.Thursday &  days.Thursday) |
                (DOW == DayOfWeek.Friday &  days.Friday) |
                (DOW == DayOfWeek.Saturday &  days.Saturday)
               )
            {
                Days += 1;
            }
        }
        return Days;
    }

我几乎肯定这可以在没有循环的情况下完成,但我似乎无法弄清楚。有人可以帮我找到更有效的算法吗?

【问题讨论】:

标签: c# algorithm datetime


【解决方案1】:

求 From 和 To 日期之间的周数(使用减法和除法)。然后将其乘以每周工作的天数。对结束案例做一些减法(从/到日期在一周的中间)。

【讨论】:

    【解决方案2】:

    嗯嗯....

    创建一个字典,从DayOfWeek(如果我没记错的话是int)到bool 然后......

    var DaysWorked = (from dayoffset in Enumerable.Range(0, (To - From).TotalDays)
                      where WorkingDays[From.AddDays(dayoffset).DayOfWeek]
                      select dayoffset).Count();
    

    虽然效率不高!

    【讨论】:

      【解决方案3】:

      看看这个codeproject article,它解释了如何在不循环的情况下做到这一点;)

      编辑:这是它使用的公式:

      1. 以周为单位计算时间跨度数。叫它吧,W。
      2. 从周数中减去第一周。 W= W-1
      3. 将周数乘以每周的工作日数。 叫它,D。
      4. 找出指定时间段内的假期。叫它,H。
      5. 计算第一周的天数。就这样吧,SD。
      6. 计算上周的天数。就这样吧,ED。
      7. 总结所有的日子。 BD = D + SD + ED × H。

      【讨论】:

      • 但是如果你阅读了算法是如何工作的,你就不需要循环了。您需要做的就是计算开始和结束周的工作天数(如果它们是部分的),其余的您可以根据您知道每周工作了多少天来计算
      • 基本上是@Mannimarco 所说的,但codeproject 网站上的公式将是您尝试做的一个好的开始
      【解决方案4】:

      您可以利用一周中的几天每 7 天重复一次这一事实。以下是算法的基本概述:

      1. 计算第一周的工作天数。
      2. 计算最后一周的工作天数。
      3. 计算中间的整周数,然后乘以一周的工作天数。
      4. 将上述三个值相加。

      【讨论】:

        【解决方案5】:
        var workDays = new DayOfWeek[]{ DayOfWeek.Monday, DayOfWeek.Tuesday};
        var days = TotalWorkDays(new DateTime(2005,1,12), new DateTime(2005,3,15), workDays);
        
        protected int TotalWorkDays(DateTime start, DateTime end, DayOfWeek[] workDays)
        {
            var weeks = (int)Math.Floor((end - start).TotalDays / 7); 
            var days = weeks * workDays.Length;
        
            //Calc rest
            var d = start.AddDays(weeks * 7);
            while (d <= end)
            {
                if(workDays.Contains(d.DayOfWeek)) 
                    days++;
                d = d.AddDays(1);
        
            }   
            return days;
        }
        

        【讨论】:

          【解决方案6】:

          您可以使用以下算法:

          • 计算开始周的工作日(最多 7 次迭代)
          • 计算开始/结束之间的周数以及工作日的多个周数
          • 计算最后一周的工作日(最多 7 次迭代)

          示例使用Time Period Library for .NET

          WeekDateDiff
          // ----------------------------------------------------------------------
          public int CountWorkingDays( DateTime start, DateTime end, IList<DayOfWeek> workingDays )
          {
            if ( workingDays.Count == 0 )
            {
              return 0;
            }
          
            Week startWeek = new Week( start );
            Week endWeek = new Week( end );
            int dayCount = 0;
          
            // start week
            DateTime currentDay = start.Date;
            while ( currentDay < startWeek.End )
            {
              if ( workingDays.Contains( currentDay.DayOfWeek ) )
              {
                dayCount++;
              }
              currentDay = currentDay.AddDays( 1 );
            }
          
            // between weeks
            DateDiff inBetweenWeekDiff = new DateDiff( startWeek.End, endWeek.Start );
            dayCount += inBetweenWeekDiff.Weeks * workingDays.Count;
          
            // end week
            currentDay = endWeek.Start.Date;
            while ( currentDay < end )
            {
              if ( workingDays.Contains( currentDay.DayOfWeek ) )
              {
                dayCount++;
              }
              currentDay = currentDay.AddDays( 1 );
            }
          
            return dayCount;
          } // CountWorkingDays
          

          用法:

          // ----------------------------------------------------------------------
          public void CountWorkingDaysSample()
          {
            DayOfWeek[] workingDays = new [] { DayOfWeek.Monday, DayOfWeek.Tuesday };
            DateTime start = new DateTime( 2011, 3, 1 );
            DateTime end = new DateTime( 2011, 5, 1 );
            Console.WriteLine( "working days: {0}", CountWorkingDays( start, end, workingDays ) );
            // > working days: 19
          } // CountWorkingDaysSample
          

          【讨论】:

            猜你喜欢
            • 2015-05-05
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-04-23
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多