Подсчет обычных рабочих дней за определенный период времени - PullRequest
8 голосов
/ 14 сентября 2010

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

Мне нужен примерно такой алгоритм в C #:

    int GetRegularWorkingDays(DateTime startDate, DateTime endDate)
    {

       int nonWorkingDays = ((endDate - startDate) % 7) * 2;

       return (endDate - startDate) - nonWorkingDays;
    }

Я знаю, что мой черновик еще далеко :(. Заранее спасибо. =)

PS: Ребята, пожалуйста, проголосуйте за лучший / самый быстрый / самый эффективный ответ ниже.Спасибо =)

Ответы [ 8 ]

18 голосов
/ 14 сентября 2010

Извлеките этот пример в Code Project , который использует очень эффективный способ, не требующий зацикливания;)

Он использует этот логарифм:

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

Я написал расширитель типов, чтобы разрешить мне добавлять (или вычитать) дни недели к определенной дате.Может быть, это поможет вам.Прекрасно работает, поэтому, пожалуйста, проголосуйте за мой пост, если вам это помогло.

    /// <summary>
    /// Adds weekdays to date
    /// </summary>
    /// <param name="value">DateTime to add to</param>
    /// <param name="weekdays">Number of weekdays to add</param>
    /// <returns>DateTime</returns>
    public static DateTime AddWeekdays(this DateTime value, int weekdays)
    {
        int direction = Math.Sign(weekdays);
        int initialDayOfWeek = Convert.ToInt32(value.DayOfWeek);

        //---------------------------------------------------------------------------
        // if the day is a weekend, shift to the next weekday before calculating
        if ((value.DayOfWeek == DayOfWeek.Sunday && direction < 0)
            || (value.DayOfWeek == DayOfWeek.Saturday && direction > 0))
        {
            value = value.AddDays(direction * 2);
            weekdays += (direction * -1); // adjust days to add by one
        }
        else if ((value.DayOfWeek == DayOfWeek.Sunday && direction > 0)
            || (value.DayOfWeek == DayOfWeek.Saturday && direction < 0))
        {
            value = value.AddDays(direction);
            weekdays += (direction * -1); // adjust days to add by one
        }
        //---------------------------------------------------------------------------

        int weeksBase = Math.Abs(weekdays / 5);
        int addDays = Math.Abs(weekdays % 5);

        int totalDays = (weeksBase * 7) + addDays;
        DateTime result = value.AddDays(totalDays * direction);

        //---------------------------------------------------------------------------
        // if the result is a weekend, shift to the next weekday
        if ((result.DayOfWeek == DayOfWeek.Sunday && direction > 0)
            || (result.DayOfWeek == DayOfWeek.Saturday && direction < 0))
        {
            result = result.AddDays(direction);
        }
        else if ((result.DayOfWeek == DayOfWeek.Sunday && direction < 0)
            || (result.DayOfWeek == DayOfWeek.Saturday && direction > 0))
        {
            result = result.AddDays(direction * 2);
        }
        //---------------------------------------------------------------------------

        return result;
    }
4 голосов
/ 14 сентября 2010

Один лайнер!

int workingDays = Enumerable.Range(0, Convert.ToInt32(endDate.Subtract(startDate).TotalDays)).Select(i=>new [] { DayOfWeek.Saturday, DayOfWeek.Sunday }.Contains(startDate.AddDays(i).DayOfWeek) ? 0 : 1).Sum();

Или более эффективно:

DayOfWeek currDay = startDate.DayOfWeek;
int nonWorkingDays = 0;

foreach(var i in Enumerable.Range(0, Convert.ToInt32(endDate.Subtract(startDate).TotalDays)))
{
     if(currDay == DayOfWeek.Sunday || currDay == DayOfWeek.Saturday) 
          nonWorkingDays++;
     if((int)++currDay > 6) currDay = (DayOfWeek)0;
}
2 голосов
/ 14 сентября 2010

Не очень быстро, но это поможет:

int GetRegularWorkingDays(DateTime start, DateTime end)
{
    return (
        from day in Range(start, end)
        where day.DayOfWeek != DayOfWeek.Saturday
        where day.DayOfWeek != DayOfWeek.Sunday
        select day).Count();
}

IEnumerable<DateTime> Range(DateTime start, DateTime end)
{
    while (start <= end)
    {
        yield return start;
        start = start.AddDays(1);
    }
}
2 голосов
/ 14 сентября 2010

Вы можете попробовать простой способ просто считать дни. Если это обычно выполняется в течение периодов времени, например месяцев, а не лет, и не вызывается повторно, то это не будет ударом по производительности, чтобы просто пройтись по нему.

int GetWorkingDays(DateTime startDate, DateTime endDate)
{
    int count = 0;
    for (DateTime currentDate = startDate; currentDate < endDate; currentDate = currentDate.AddDays(1))
    {
        if (currentDate.DayOfWeek == DayOfWeek.Sunday || currentDate.DayOfWeek == DayOfWeek.Saturday)
        {
            continue;
        }
        count++;
    }
    return count;
}
1 голос
/ 14 сентября 2010

Вы можете сделать это с помощью вспомогательного класса временной шкалы - этот класс также допускает другие интервалы:

public class TimeLine
{
    public static IEnumerable<DateTime> CreateTimeLine(DateTime start, TimeSpan interval) {
        return TimeLine.CreateTimeLine(start, interval, DateTime.MaxValue);
    }

    public static IEnumerable<DateTime> CreateTimeLine(DateTime start, TimeSpan interval, DateTime end) {
        var currentVal = start;
        var endVal = end.Subtract(interval);

        do {
            currentVal = currentVal.Add(interval);
            yield return currentVal;
        } while (currentVal <= endVal);
    }
}

Для решения вашей проблемы вы можете сделать следующее:

var workingDays = TimeLine.CreateTimeLine(DateTime.Now.Date, TimeSpan.FromDays(1), DateTime.Now.Date.AddDays(30))
                          .Where(x => x.DayOfWeek != DayOfWeek.Saturday && x.DayOfWeek != DayOfWeek.Sunday);
var noOfWorkingDays = workingDays.Count();

Этот класс временной шкалы можно использовать для любой непрерывной временной шкалы любого интервала.

0 голосов
/ 20 марта 2012
int count = 0;
switch (dateTimePicker2.Value.DayOfWeek.ToString())
{
    case "Saturday": count--; break;
    case "Sunday": count--; break;
    default:break;
}
switch (dateTimePicker3.Value.DayOfWeek.ToString())
{
    case "Saturday": count--; break;
    case "Sunday": count--; break;
    default:break;
}
if (count == -2)
    count = -1;
int weeks = t.Days / 7;
int daycount =count+ t.Days - (2 * weeks)+1;
label7.Text = "No of Days : " + daycount.ToString();
0 голосов
/ 14 сентября 2010

Простой способ получить рабочие дни:

int GetRegularWorkingDays(DateTime startDate, DateTime endDate)
{
    int total = 0;

    if (startDate < endDate)
    {
        var days = endDate - startDate;

        for( ; startDate < endDate; startDate = startDate.AddDays(1) )
        {
            switch(startDate.DayOfWeek)
            {
                case DayOfWeek.Saturday :
                case DayOfWeek.Sunday :                     
                    break;
                default:
                    total++;
                    break;
            }
        }
    }
    return total;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...