[c#] AddBusinessDays 및 GetBusinessDays

2 개의 우아한 완전한 구현을 찾아야합니다.

public static DateTime AddBusinessDays(this DateTime date, int days)
{
 // code here
}

and 

public static int GetBusinessDays(this DateTime start, DateTime end)
{
 // code here
}

O (1) 선호 (루프 없음).

편집 : 영업일은 근무일 (월요일, 화요일, 수요일, 목요일, 금요일)을 의미합니다. 공휴일은없고 주말 만 제외됩니다.

이미 작동하는 것처럼 보이는 추악한 솔루션이 있지만 이것을 수행하는 우아한 방법이 있는지 궁금합니다. 감사


이것이 내가 지금까지 쓴 것입니다. 모든 경우에 작동하며 부정적이기도합니다. 여전히 GetBusinessDays 구현이 필요합니다.

public static DateTime AddBusinessDays(this DateTime startDate,
                                         int businessDays)
{
    int direction = Math.Sign(businessDays);
    if(direction == 1)
    {
        if(startDate.DayOfWeek == DayOfWeek.Saturday)
        {
            startDate = startDate.AddDays(2);
            businessDays = businessDays - 1;
        }
        else if(startDate.DayOfWeek == DayOfWeek.Sunday)
        {
            startDate = startDate.AddDays(1);
            businessDays = businessDays - 1;
        }
    }
    else
    {
        if(startDate.DayOfWeek == DayOfWeek.Saturday)
        {
            startDate = startDate.AddDays(-1);
            businessDays = businessDays + 1;
        }
        else if(startDate.DayOfWeek == DayOfWeek.Sunday)
        {
            startDate = startDate.AddDays(-2);
            businessDays = businessDays + 1;
        }
    }

    int initialDayOfWeek = (int)startDate.DayOfWeek;

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

    if((direction == 1 && addDays + initialDayOfWeek > 5) ||
         (direction == -1 && addDays >= initialDayOfWeek))
    {
        addDays += 2;
    }

    int totalDays = (weeksBase * 7) + addDays;
    return startDate.AddDays(totalDays * direction);
}



답변

첫 번째 기능에 대한 최근 시도 :

public static DateTime AddBusinessDays(DateTime date, int days)
{
    if (days < 0)
    {
        throw new ArgumentException("days cannot be negative", "days");
    }

    if (days == 0) return date;

    if (date.DayOfWeek == DayOfWeek.Saturday)
    {
        date = date.AddDays(2);
        days -= 1;
    }
    else if (date.DayOfWeek == DayOfWeek.Sunday)
    {
        date = date.AddDays(1);
        days -= 1;
    }

    date = date.AddDays(days / 5 * 7);
    int extraDays = days % 5;

    if ((int)date.DayOfWeek + extraDays > 5)
    {
        extraDays += 2;
    }

    return date.AddDays(extraDays);

}

두 번째 함수 인 GetBusinessDays는 다음과 같이 구현할 수 있습니다.

public static int GetBusinessDays(DateTime start, DateTime end)
{
    if (start.DayOfWeek == DayOfWeek.Saturday)
    {
        start = start.AddDays(2);
    }
    else if (start.DayOfWeek == DayOfWeek.Sunday)
    {
        start = start.AddDays(1);
    }

    if (end.DayOfWeek == DayOfWeek.Saturday)
    {
        end = end.AddDays(-1);
    }
    else if (end.DayOfWeek == DayOfWeek.Sunday)
    {
        end = end.AddDays(-2);
    }

    int diff = (int)end.Subtract(start).TotalDays;

    int result = diff / 7 * 5 + diff % 7;

    if (end.DayOfWeek < start.DayOfWeek)
    {
        return result - 2;
    }
    else{
        return result;
    }
}


답변

사용 유창함 날짜 시간을 :

var now = DateTime.Now;
var dateTime1 = now.AddBusinessDays(3);
var dateTime2 = now.SubtractBusinessDays(5);

내부 코드는 다음과 같습니다

    /// <summary>
    /// Adds the given number of business days to the <see cref="DateTime"/>.
    /// </summary>
    /// <param name="current">The date to be changed.</param>
    /// <param name="days">Number of business days to be added.</param>
    /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
    public static DateTime AddBusinessDays(this DateTime current, int days)
    {
        var sign = Math.Sign(days);
        var unsignedDays = Math.Abs(days);
        for (var i = 0; i < unsignedDays; i++)
        {
            do
            {
                current = current.AddDays(sign);
            }
            while (current.DayOfWeek == DayOfWeek.Saturday ||
                current.DayOfWeek == DayOfWeek.Sunday);
        }
        return current;
    }

    /// <summary>
    /// Subtracts the given number of business days to the <see cref="DateTime"/>.
    /// </summary>
    /// <param name="current">The date to be changed.</param>
    /// <param name="days">Number of business days to be subtracted.</param>
    /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
    public static DateTime SubtractBusinessDays(this DateTime current, int days)
    {
        return AddBusinessDays(current, -days);
    }


답변

영업일을 더하거나 뺄 수있는 확장 프로그램을 만들었습니다. 빼려면 음수 businessDays를 사용하십시오. 상당히 우아한 해결책이라고 생각합니다. 모든 경우에 작동하는 것 같습니다.

namespace Extensions.DateTime
{
    public static class BusinessDays
    {
        public static System.DateTime AddBusinessDays(this System.DateTime source, int businessDays)
        {
            var dayOfWeek = businessDays < 0
                                ? ((int)source.DayOfWeek - 12) % 7
                                : ((int)source.DayOfWeek + 6) % 7;

            switch (dayOfWeek)
            {
                case 6:
                    businessDays--;
                    break;
                case -6:
                    businessDays++;
                    break;
            }

            return source.AddDays(businessDays + ((businessDays + dayOfWeek) / 5) * 2);
        }
    }
}

예:

using System;
using System.Windows.Forms;
using Extensions.DateTime;

namespace AddBusinessDaysTest
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            label1.Text = DateTime.Now.AddBusinessDays(5).ToString();
            label2.Text = DateTime.Now.AddBusinessDays(-36).ToString();
        }
    }
}


답변

저에게는 주말을 건너 뛰고 부정적이거나 긍정적 인 해결책이 있어야했습니다. 내 기준은 앞으로 나아 갔다가 주말에 착륙하면 월요일로 진행해야한다는 것이 었습니다. 돌아가서 주말에 착륙했다면 금요일로 점프해야합니다.

예를 들면 :

  • 수요일-영업일 기준 3 일 = 지난 금요일
  • 수요일 + 영업일 3 일 = 월요일
  • 금요일-영업일 기준 7 일 = 지난 수요일
  • 화요일-영업일 기준 5 일 = 마지막 화요일

글쎄 당신은 아이디어를 얻습니다.)

이 확장 클래스를 작성하게되었습니다.

public static partial class MyExtensions
{
    public static DateTime AddBusinessDays(this DateTime date, int addDays)
    {
        while (addDays != 0)
        {
            date = date.AddDays(Math.Sign(addDays));
            if (MyClass.IsBusinessDay(date))
            {
                addDays = addDays - Math.Sign(addDays);
            }
        }
        return date;
    }
}

다른 곳에서 사용하는 것이 유용하다고 생각한이 방법을 사용합니다.

public class MyClass
{
    public static bool IsBusinessDay(DateTime date)
    {
        switch (date.DayOfWeek)
        {
            case DayOfWeek.Monday:
            case DayOfWeek.Tuesday:
            case DayOfWeek.Wednesday:
            case DayOfWeek.Thursday:
            case DayOfWeek.Friday:
                return true;
            default:
                return false;
        }
    }
}

당신이 그것을 귀찮게하고 싶지 않다면 그냥 if (MyClass.IsBusinessDay(date))ifif ((date.DayOfWeek != DayOfWeek.Saturday) && (date.DayOfWeek != DayOfWeek.Sunday))

이제 할 수 있습니다

var myDate = DateTime.Now.AddBusinessDays(-3);

또는

var myDate = DateTime.Now.AddBusinessDays(5);

다음은 몇 가지 테스트 결과입니다.

예상 결과 테스트
수요일 -4 영업일 목요일 목요일
수요일 -3 영업일 금요일 금요일
수요일 +3 영업일 월요일 월요일
금요일 -7 영업일 수요일 수요일
화요일 -5 영업일 화요일 화요일
금요일 +1 영업일 월요일 월요일
토요일 +1 영업일 월요일 월요일
일요일 -1 영업일 금요일 금요일
월요일 -1 영업일 금요일 금요일
월요일 +1 영업일 화요일 화요일
월요일 +0 영업일 월요일 월요일


답변

public static DateTime AddBusinessDays(this DateTime date, int days)
{
    date = date.AddDays((days / 5) * 7);

    int remainder = days % 5;

    switch (date.DayOfWeek)
    {
        case DayOfWeek.Tuesday:
            if (remainder > 3) date = date.AddDays(2);
            break;
        case DayOfWeek.Wednesday:
            if (remainder > 2) date = date.AddDays(2);
            break;
        case DayOfWeek.Thursday:
            if (remainder > 1) date = date.AddDays(2);
            break;
        case DayOfWeek.Friday:
            if (remainder > 0) date = date.AddDays(2);
            break;
        case DayOfWeek.Saturday:
            if (days > 0) date = date.AddDays((remainder == 0) ? 2 : 1);
            break;
        case DayOfWeek.Sunday:
            if (days > 0) date = date.AddDays((remainder == 0) ? 1 : 0);
            break;
        default:  // monday
            break;
    }

    return date.AddDays(remainder);
}


답변

답변에 늦었지만 근무일에 간단한 작업을 수행하는 데 필요한 모든 사용자 정의가 포함 된 작은 라이브러리를 만들었습니다. 여기에 남겨 둡니다 : Working Days Management


답변

유일한 해결책은 이러한 통화가 비즈니스 캘린더를 정의하는 데이터베이스 테이블에 액세스하도록하는 것입니다. 너무 어렵지 않게 월요일부터 금요일까지 근무하는 동안 코딩 할 수 있지만 휴일을 처리하는 것은 어려울 것입니다.

우아하지 않고 테스트되지 않은 부분 솔루션을 추가하도록 편집되었습니다.

public static DateTime AddBusinessDays(this DateTime date, int days)
{
    for (int index = 0; index < days; index++)
    {
        switch (date.DayOfWeek)
        {
            case DayOfWeek.Friday:
                date = date.AddDays(3);
                break;
            case DayOfWeek.Saturday:
                date = date.AddDays(2);
                break;
            default:
                date = date.AddDays(1);
                break;
         }
    }
    return date;
}

또한 루프 없음 요구 사항을 위반했습니다.