AddBusinessDays 및 GetBusinessDays


93

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

14
날짜만큼 비논리적 인 것에 관한 우아한 해결책이 있습니까?
Wyatt Barnett

휴일에 관심이 있습니까? – 제임스 코니 글 리아로. 없음
아드리안 Zanescu

9
돕고 자하는 사람들에게 투표하는 것은이기는 전략이 아닙니다.
Jamie Ide 2009-06-25

1
AddBusinessDays위 질문 의 구현에 대한 간략한 참고 사항 (실제로 삭제 취소를 제안한 삭제 된 답변, 대신 질문에 대한 답변을 복사 한 모드) : 내 의견으로는이 솔루션이 지금까지의 모든 답변보다 낫습니다. 소스로 토요일과 일요일의 음수 값을 올바르게 처리하고 타사 라이브러리가 필요하지 않습니다. (여기에서 다른 솔루션을 테스트하기위한 작은 프로그램을 만들었습니다.) if (businessDays == 0) return startDate;이 에지 케이스에 대한 올바른 결과를 얻기 위해 메서드 시작 부분 에만 추가 합니다.
Slauma 2014

1
@AZ .: 첫 번째 삭제는 꽤 오래되었습니다. 답변 삭제 취소 요청 후 모드는 답변 삭제를 취소하여 (30 초 동안) 질문 아래의 내용을 복사 한 다음 다시 삭제했습니다. 이것이 귀하의 답변에 최근 삭제 타임 스탬프가있는 이유입니다. 내 목적을 위해 AddBusinessDays내가 필요한 모든 경우에서 작동하는 가장 일반적인 솔루션 이기 때문에 위의 의견을 썼습니다 . 코드 덕분에 현재 프로젝트 중 하나에 복사했습니다 (약간 수정하고 C ++로 번역 한 후). 모든 엣지 케이스를 올바르게 처리하는 것이 놀랍도록 어렵 기 때문에 많은 도움이되었습니다.
Slauma 2014

답변:


134

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

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

두 번째 솔루션의 경우 한 가지 해결책은 날짜와 날짜 + 일의 차이를 가져 오는 것입니다. 이것은 두 기능이 제대로 동기화되도록 보장하고 중복성을 제거한다는 점에서 좋습니다.
Brian

현재 날짜를 입력하고 0 ~ 10 영업일 동안 실행하며 항상 수요일에 실패합니다.
Adrian Godong

1
그래, 우리는 결국 거기에 도착했다. (나는 나의 작은 기여에 대해 '우리'라고 말한다!) 노력에 찬성 투표했다.
Noldorin 2009-06-25

Noldorin의 의견을 보내 주셔서 감사합니다. 유감스럽게도 귀하의 의견에 찬성 투표를 할 수 있습니다!
Patrick McDonald

3
DateTime.AddDays는 음수로 작동합니다. AddBusinessDays에 음수를 사용하면 비업무 일을 선택할 수있는 것과 동일한 패턴을 올바르게 따르지 않습니다.
Ristogod

63

사용 유창함 날짜 시간을 :

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

이것은 VB.Net으로 변환했을 때 실제로 효과가 있었던 유일한 솔루션입니다.
Nicholas

1
OP는 루프를 요청하지 않았지만 이것은 분명히 루프를 가지고 있습니다. 가장 효율적이지 않은 방식으로 무언가를하는 것은 우아하지 않습니다.
Neolisk

13

영업일을 더하거나 뺄 수있는 확장 프로그램을 만들었습니다. 빼려면 음수 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();
        }
    }
}

소스 날짜가 토요일인지 일요일인지 결과는 의심 스럽습니다. 예 : 토요일 + 1 영업일은 화요일이되고 월요일을 예상합니다.
Slauma 2014.04.18

3
@Slauma : 이것이 캐나다의 대부분의 기업이 운영하는 방식입니다. +1 영업일 = ​​"다음 영업일"(토요일의 경우 화요일) 월요일은 "동일 영업일"입니다.
Neolisk

3
@Slauma 프로그램은 의도 한대로 작동합니다. 논리적으로 생각하십시오. 토요일에 업무와 관련된 일이 시작되고 해당 업무 일 동안 사람들이 반응 할 수 있도록 업무 일 기준 1 일을 허용해야하는 경우 월요일까지 완료해야한다고 말하는 것이 합리적일까요?!
Riegardt Steyn

8

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

예를 들면 :

  • 수요일-영업일 기준 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 bool IsBusinessDay (이 DateTime 날짜)
Andy B

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

1

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


2
불행히도 이것은 GNU 라이센스이므로 모든 상용 앱에 대한 "법적 독"입니다. 이걸 "MIT"나 "Apache"로 편하게 해주실 수 있을까요?
토니 O'Hagan

일부 정적 목록은 연결 목록이 아닌 배열이어야합니다.
토니 O'Hagan

1
방금 라이센스를 MIT로 변경했습니다 (그렇게 간단한 것에 대해 아무것도 차단하고 싶지 않습니다). 나는 당신의 다른 제안을 조사 할 것입니다.
Boneless

일부 국가에서는 월요일부터 금요일까지 다른 근무일이있을 수 있으므로 국가 별 근무일 관리를 보는 것이 흥미로울 것입니다.
serializer

1

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

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

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

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


토요일 사건이 맞을 거라고는 생각하지 않습니다.
CoderDennis

@Dennis-지나간 날짜가 토요일이면 그럴 것입니다.
Jamie Ide

나는 그것을 작동시키기 위해 당신의 코드를 자유롭게 편집 할 수 있었다. 다음에 게시하기 전에 코드를 테스트 해주세요. 감사합니다.
bytecode77

그리고 나는 제로 찬성 투표가 스스로를 말하는 것으로 생각했습니다. 감사!
Jamie Ide 2016 년

1

오늘은 토요일일요일 평일뿐 아니라 공휴일도 제외 할 방법을 찾아야했기 때문에이 포스트를 부활시키고 있습니다. 보다 구체적으로 다음과 같은 다양한 휴일을 처리해야했습니다.

  • 국가 불변 공휴일 (최소한 1 월 1 일과 같은 서구 국가의 경우).
  • 계산 된 휴일 (예 : 부활절 및 부활절 월요일).
  • 국가 별 공휴일 (예 : 이탈리아 해방의 날 또는 미국 ID4).
  • 도시 별 공휴일 (예 : 로마 성 수호의 날).
  • 기타 맞춤식 공휴일 (예 : "내일 사무실 휴무").

결국 다음과 같은 도우미 / 확장 클래스 세트를 만들었습니다. 노골적으로 우아하지는 않지만 비효율적 인 루프를 많이 사용하므로 내 문제를 영원히 해결할 수있을만큼 괜찮습니다. 이 게시물의 전체 소스 코드를 다른 사람에게도 유용하게 사용하기를 바라며 여기에 드롭합니다.

소스 코드

/// <summary>
/// Helper/extension class for manipulating date and time values.
/// </summary>
public static class DateTimeExtensions
{
    /// <summary>
    /// Calculates the absolute year difference between two dates.
    /// </summary>
    /// <param name="dt1"></param>
    /// <param name="dt2"></param>
    /// <returns>A whole number representing the number of full years between the specified dates.</returns>
    public static int Years(DateTime dt1,DateTime dt2)
    {
        return Months(dt1,dt2)/12;
        //if (dt2<dt1)
        //{
        //    DateTime dt0=dt1;
        //    dt1=dt2;
        //    dt2=dt0;
        //}

        //int diff=dt2.Year-dt1.Year;
        //int m1=dt1.Month;
        //int m2=dt2.Month;
        //if (m2>m1) return diff;
        //if (m2==m1 && dt2.Day>=dt1.Day) return diff;
        //return (diff-1);
    }

    /// <summary>
    /// Calculates the absolute year difference between two dates.
    /// Alternative, stand-alone version (without other DateTimeUtil dependency nesting required)
    /// </summary>
    /// <param name="start"></param>
    /// <param name="end"></param>
    /// <returns></returns>
    public static int Years2(DateTime start, DateTime end)
    {
        return (end.Year - start.Year - 1) +
            (((end.Month > start.Month) ||
            ((end.Month == start.Month) && (end.Day >= start.Day))) ? 1 : 0);
    }

    /// <summary>
    /// Calculates the absolute month difference between two dates.
    /// </summary>
    /// <param name="dt1"></param>
    /// <param name="dt2"></param>
    /// <returns>A whole number representing the number of full months between the specified dates.</returns>
    public static int Months(DateTime dt1,DateTime dt2)
    {
        if (dt2<dt1)
        {
            DateTime dt0=dt1;
            dt1=dt2;
            dt2=dt0;
        }

        dt2=dt2.AddDays(-(dt1.Day-1));
        return (dt2.Year-dt1.Year)*12+(dt2.Month-dt1.Month);
    }

    /// <summary>
    /// Returns the higher of the two date time values.
    /// </summary>
    /// <param name="dt1">The first of the two <c>DateTime</c> values to compare.</param>
    /// <param name="dt2">The second of the two <c>DateTime</c> values to compare.</param>
    /// <returns><c>dt1</c> or <c>dt2</c>, whichever is higher.</returns>
    public static DateTime Max(DateTime dt1,DateTime dt2)
    {
        return (dt2>dt1?dt2:dt1);
    }

    /// <summary>
    /// Returns the lower of the two date time values.
    /// </summary>
    /// <param name="dt1">The first of the two <c>DateTime</c> values to compare.</param>
    /// <param name="dt2">The second of the two <c>DateTime</c> values to compare.</param>
    /// <returns><c>dt1</c> or <c>dt2</c>, whichever is lower.</returns>
    public static DateTime Min(DateTime dt1,DateTime dt2)
    {
        return (dt2<dt1?dt2:dt1);
    }

    /// <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>
    /// <param name="holidays">An optional list of holiday (non-business) days to consider.</param>
    /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
    public static DateTime AddBusinessDays(
        this DateTime current, 
        int days, 
        IEnumerable<DateTime> holidays = null)
    {
        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
                || (holidays != null && holidays.Contains(current.Date))
                );
        }
        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>
    /// <param name="holidays">An optional list of holiday (non-business) days to consider.</param>
    /// <returns>A <see cref="DateTime"/> increased by a given number of business days.</returns>
    public static DateTime SubtractBusinessDays(
        this DateTime current, 
        int days,
        IEnumerable<DateTime> holidays)
    {
        return AddBusinessDays(current, -days, holidays);
    }

    /// <summary>
    /// Retrieves the number of business days from two dates
    /// </summary>
    /// <param name="startDate">The inclusive start date</param>
    /// <param name="endDate">The inclusive end date</param>
    /// <param name="holidays">An optional list of holiday (non-business) days to consider.</param>
    /// <returns></returns>
    public static int GetBusinessDays(
        this DateTime startDate, 
        DateTime endDate,
        IEnumerable<DateTime> holidays)
    {
        if (startDate > endDate)
            throw new NotSupportedException("ERROR: [startDate] cannot be greater than [endDate].");

        int cnt = 0;
        for (var current = startDate; current < endDate; current = current.AddDays(1))
        {
            if (current.DayOfWeek == DayOfWeek.Saturday
                || current.DayOfWeek == DayOfWeek.Sunday
                || (holidays != null && holidays.Contains(current.Date))
                )
            {
                // skip holiday
            }
            else cnt++;
        }
        return cnt;
    }

    /// <summary>
    /// Calculate Easter Sunday for any given year.
    /// src.: https://stackoverflow.com/a/2510411/1233379
    /// </summary>
    /// <param name="year">The year to calcolate Easter against.</param>
    /// <returns>a DateTime object containing the Easter month and day for the given year</returns>
    public static DateTime GetEasterSunday(int year)
    {
        int day = 0;
        int month = 0;

        int g = year % 19;
        int c = year / 100;
        int h = (c - (int)(c / 4) - (int)((8 * c + 13) / 25) + 19 * g + 15) % 30;
        int i = h - (int)(h / 28) * (1 - (int)(h / 28) * (int)(29 / (h + 1)) * (int)((21 - g) / 11));

        day = i - ((year + (int)(year / 4) + i + 2 - c + (int)(c / 4)) % 7) + 28;
        month = 3;

        if (day > 31)
        {
            month++;
            day -= 31;
        }

        return new DateTime(year, month, day);
    }

    /// <summary>
    /// Retrieve holidays for given years
    /// </summary>
    /// <param name="years">an array of years to retrieve the holidays</param>
    /// <param name="countryCode">a country two letter ISO (ex.: "IT") to add the holidays specific for that country</param>
    /// <param name="cityName">a city name to add the holidays specific for that city</param>
    /// <returns></returns>
    public static IEnumerable<DateTime> GetHolidays(IEnumerable<int> years, string countryCode = null, string cityName = null)
    {
        var lst = new List<DateTime>();

        foreach (var year in years.Distinct())
        {
            lst.AddRange(new[] {
                new DateTime(year, 1, 1),       // 1 gennaio (capodanno)
                new DateTime(year, 1, 6),       // 6 gennaio (epifania)
                new DateTime(year, 5, 1),       // 1 maggio (lavoro)
                new DateTime(year, 8, 15),      // 15 agosto (ferragosto)
                new DateTime(year, 11, 1),      // 1 novembre (ognissanti)
                new DateTime(year, 12, 8),      // 8 dicembre (immacolata concezione)
                new DateTime(year, 12, 25),     // 25 dicembre (natale)
                new DateTime(year, 12, 26)      // 26 dicembre (s. stefano)
            });

            // add easter sunday (pasqua) and monday (pasquetta)
            var easterDate = GetEasterSunday(year);
            lst.Add(easterDate);
            lst.Add(easterDate.AddDays(1));

            // country-specific holidays
            if (!String.IsNullOrEmpty(countryCode))
            {
                switch (countryCode.ToUpper())
                {
                    case "IT":
                        lst.Add(new DateTime(year, 4, 25));     // 25 aprile (liberazione)
                        break;
                    case "US":
                        lst.Add(new DateTime(year, 7, 4));     // 4 luglio (Independence Day)
                        break;

                    // todo: add other countries

                    case default:
                        // unsupported country: do nothing
                        break;
                }
            }

            // city-specific holidays
            if (!String.IsNullOrEmpty(cityName))
            {
                switch (cityName)
                {
                    case "Rome":
                    case "Roma":
                        lst.Add(new DateTime(year, 6, 29));  // 29 giugno (s. pietro e paolo)
                        break;
                    case "Milano":
                    case "Milan":
                        lst.Add(new DateTime(year, 12, 7));  // 7 dicembre (s. ambrogio)
                        break;

                    // todo: add other cities

                    default:
                        // unsupported city: do nothing
                        break;

                }
            }
        }
        return lst;
    }
}

사용 정보

코드는 매우 자명하지만 여기에 사용 방법을 설명하는 몇 가지 예가 있습니다.

영업일 기준 10 일 추가 (토요일 및 일요일 평일 만 건너 뛰기)

var dtResult = DateTimeUtil.AddBusinessDays(srcDate, 10);

영업일 기준 10 일 추가 (2019 년 토요일, 일요일 및 모든 국가 불변 공휴일 건너 뛰기)

var dtResult = DateTimeUtil.AddBusinessDays(srcDate, 10, GetHolidays(2019));

영업일 기준 10 일 추가 (2019 년 토요일, 일요일 및 모든 이탈리아 공휴일 제외)

var dtResult = DateTimeUtil.AddBusinessDays(srcDate, 10, GetHolidays(2019, "IT"));

영업일 기준 10 일 추가 (토요일, 일요일, 모든 이탈리아 공휴일 및 2019 년 로마 특정 공휴일 제외)

var dtResult = DateTimeUtil.AddBusinessDays(srcDate, 10, GetHolidays(2019, "IT", "Rome"));

위의 함수와 코드 예제는 블로그 게시물에서 자세히 설명 합니다.


0
    public static DateTime AddBusinessDays(DateTime date, int days)
    {
        if (days == 0) return date;
        int i = 0;
        while (i < days)
        {
            if (!(date.DayOfWeek == DayOfWeek.Saturday ||  date.DayOfWeek == DayOfWeek.Sunday)) i++;  
            date = date.AddDays(1);
        }
        return date;
    }

미래에 :) 대답을 좀 더 컨텍스트를 추가하고이 넣어 한 이유는 아마도 당신이 무엇을
DAX

0

추가 할 음수 일수를 지원하는 "AddBusinessDays"를 원했고 결국 다음과 같이되었습니다.

// 0 == Monday, 6 == Sunday
private static int epochDayToDayOfWeek0Based(long epochDay) {
    return (int)Math.floorMod(epochDay + 3, 7);
}

public static int daysBetween(long fromEpochDay, long toEpochDay) {
    // http://stackoverflow.com/questions/1617049/calculate-the-number-of-business-days-between-two-dates
    final int fromDOW = epochDayToDayOfWeek0Based(fromEpochDay);
    final int toDOW = epochDayToDayOfWeek0Based(toEpochDay);
    long calcBusinessDays = ((toEpochDay - fromEpochDay) * 5 + (toDOW - fromDOW) * 2) / 7;

    if (toDOW   == 6) calcBusinessDays -= 1;
    if (fromDOW == 6) calcBusinessDays += 1;
    return (int)calcBusinessDays;
}

public static long addDays(long epochDay, int n) {
    // https://alecpojidaev.wordpress.com/2009/10/29/work-days-calculation-with-c/
    // NB: in .NET, Sunday == 0, but in our code Monday == 0
    final int dow = (epochDayToDayOfWeek0Based(epochDay) + 1) % 7;
    final int wds = n + (dow == 0 ? 1 : dow); // Adjusted number of working days to add, given that we now start from the immediately preceding Sunday
    final int wends = n < 0 ? ((wds - 5) / 5) * 2
                            : (wds / 5) * 2 - (wds % 5 == 0 ? 2 : 0);
    return epochDay - dow + // Find the immediately preceding Sunday
           wds +            // Add computed working days
           wends;           // Add weekends that occur within each complete working week
}

루프가 필요하지 않으므로 "대량"추가시에도 상당히 빠릅니다.

그것은 새로운 JDK8 LocalDate 클래스에 의해 노출되고 Java에서 작업하고 있었기 때문에 epoch 이후 달력 일 수로 표현 된 날짜와 함께 작동합니다. 하지만 다른 설정에 쉽게 적응할 수 있어야합니다.

기본 속성은 addDays항상 평일을 반환하고 모두 dn,daysBetween(d, addDays(d, n)) == n

이론적으로 0 일을 더하고 0 일을 빼는 것은 다른 작업이어야합니다 (날짜가 일요일 인 경우 0 일을 더하면 월요일이되고 0 일을 빼면 금요일이됩니다). 음수 0 (부동 소수점 외부!)과 같은 것이 없기 때문에 인수 n = 0을 0 일 추가 를 의미하는 것으로 해석하기로 선택했습니다 .


0

이것이 GetBusinessDays에 대한 더 간단한 방법이 될 수 있다고 생각합니다.

    public int GetBusinessDays(DateTime start, DateTime end, params DateTime[] bankHolidays)
    {
        int tld = (int)((end - start).TotalDays) + 1; //including end day
        int not_buss_day = 2 * (tld / 7); //Saturday and Sunday
        int rest = tld % 7; //rest.

        if (rest > 0)
        {
            int tmp = (int)start.DayOfWeek - 1 + rest;
            if (tmp == 6 || start.DayOfWeek == DayOfWeek.Sunday) not_buss_day++; else if (tmp > 6) not_buss_day += 2;
        }

        foreach (DateTime bankHoliday in bankHolidays)
        {
            DateTime bh = bankHoliday.Date;
            if (!(bh.DayOfWeek == DayOfWeek.Saturday || bh.DayOfWeek == DayOfWeek.Sunday) && (start <= bh && bh <= end))
            {
                not_buss_day++;
            }
        }
        return tld - not_buss_day;
    }

0

다음은 고객의 출발일과 배송일이 모두 표시된 코드입니다.

            // Calculate departure date
            TimeSpan DeliveryTime = new TimeSpan(14, 30, 0); 
            TimeSpan now = DateTime.Now.TimeOfDay;
            DateTime dt = DateTime.Now;
            if (dt.TimeOfDay > DeliveryTime) dt = dt.AddDays(1);
            if (dt.DayOfWeek == DayOfWeek.Saturday) dt = dt.AddDays(1);
            if (dt.DayOfWeek == DayOfWeek.Sunday) dt = dt.AddDays(1);
            dt = dt.Date + DeliveryTime;
            string DepartureDay = "today at "+dt.ToString("HH:mm");
            if (dt.Day!=DateTime.Now.Day)
            {
                DepartureDay = dt.ToString("dddd at HH:mm", new CultureInfo(WebContextState.CurrentUICulture));
            }
            Return DepartureDay;

            // Caclulate delivery date
            dt = dt.AddDays(1);
            if (dt.DayOfWeek == DayOfWeek.Saturday) dt = dt.AddDays(1);
            if (dt.DayOfWeek == DayOfWeek.Sunday) dt = dt.AddDays(1);
            string DeliveryDay = dt.ToString("dddd", new CultureInfo(WebContextState.CurrentUICulture));
            return DeliveryDay;

즐거운 코딩입니다.


0
public static DateTime AddWorkingDays(this DateTime date, int daysToAdd)
{
    while (daysToAdd > 0)
    {
        date = date.AddDays(1);

        if (date.DayOfWeek != DayOfWeek.Saturday && date.DayOfWeek != DayOfWeek.Sunday)
        {
            daysToAdd -= 1;
        }
    }

    return date;
}

0
public static int GetBusinessDays(this DateTime start, DateTime end)
            {
                return Enumerable.Range(0, (end- start).Days)
                                .Select(a => start.AddDays(a))
                                .Where(a => a.DayOfWeek != DayOfWeek.Sunday)
                                .Where(a => a.DayOfWeek != DayOfWeek.Saturday)
                                .Count();
    
            }

-1

이것이 누군가를 돕기를 바랍니다.

private DateTime AddWorkingDays(DateTime addToDate, int numberofDays)
    {
        addToDate= addToDate.AddDays(numberofDays);
        while (addToDate.DayOfWeek == DayOfWeek.Saturday || addToDate.DayOfWeek == DayOfWeek.Sunday)
        {
            addToDate= addToDate.AddDays(1);
        }
        return addToDate;
    }

2
이것은 올바르지 않습니다. 대부분의 경우 작동하지 않습니다. 누구에게도 도움이되지 않을 것입니다.
Neolisk
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.