Считать дни работал за неделю без циклов? - PullRequest
3 голосов
/ 16 июня 2011

Мне нужно подсчитать общее количество отработанных дней с учетом структуры, указывающей, какие дни недели проработаны, а также с и по сегодняшний день.

Мой текущий алгоритм таков:

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

Я почти уверен, что это можно сделать без цикла, но я не могу понять.Может кто-нибудь помочь мне найти более эффективный алгоритм?

Ответы [ 6 ]

4 голосов
/ 16 июня 2011

Найти количество недель между датами от и до (с использованием вычитания и деления). Затем умножьте это на количество дней, отработанных в неделю. Сделайте некоторое вычитание для конечных случаев (даты С / К находятся в середине недели).

1 голос
/ 16 июня 2011

Посмотрите на эту статью кода проекта , в которой объясняется, как сделать это без циклов;)

РЕДАКТИРОВАТЬ: Вот формула, которую он использует:

  1. Рассчитать количество промежутков времени в неделях.Назовите это, W.
  2. Вычтите первую неделю из числа недель.W = W-1
  3. Умножьте количество недель на количество рабочих дней в неделю.Назовите это, D.
  4. Узнайте праздники в течение указанного промежутка времени.Назовите это, H.
  5. Подсчитайте дни первой недели.Назовите это, SD.
  6. Рассчитайте дни на прошлой неделе.Позвоните, ED.
  7. Подведите итоги всех дней.BD = D + SD + ED � H.
1 голос
/ 16 июня 2011

хммм ....

Создать словарь, начиная с DayOfWeek (int, если я правильно помню), до bool затем ....

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

Не совсем эффективно, хотя!

0 голосов
/ 16 июня 2011

Вы можете использовать следующий алгоритм:

  • считать рабочие дни начальной недели (максимум 7 итераций)
  • считать недели между началом / концом и умножать недели нарабочие дни
  • считают рабочие дни конечной недели (максимум 7 итераций)

В выборке используются классы Неделя и DateDiff Библиотека периодов времени для .NET

// ----------------------------------------------------------------------
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
0 голосов
/ 16 июня 2011
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;
}
0 голосов
/ 16 июня 2011

Вы можете воспользоваться тем, что дни недели повторяются каждые семь дней.Вот базовая схема алгоритма:

  1. Подсчет количества дней, отработанных в первой неполной неделе.
  2. Подсчет количества дней, отработанных в последней неполной неделе.
  3. Рассчитайте количество целых недель в середине и умножьте на количество дней, отработанных в неделе.
  4. Суммируйте три вышеуказанных значения.
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...