添加天数到日期但不包括周末

时间:2008-11-10 21:48:22

标签: c# f# date

给定日期我如何添加天数,但不包括周末。例如,鉴于11/12/2008(星期三),加上5将导致2008年11月19日(星期三)而不是11/17/2008(星期一)。

我可以想到一个简单的解决方案,比如循环每天添加和检查是否是周末,但我想看看是否有更优雅的东西。我也对任何F#解决方案感兴趣。

13 个答案:

答案 0 :(得分:16)

使用Fluent DateTime https://github.com/FluentDateTime/FluentDateTime

var dateTime = DateTime.Now.AddBusinessDays(4);

答案 1 :(得分:6)

public DateTime AddBusinessDays(DateTime dt, int nDays)
{
    int weeks = nDays / 5;
    nDays %= 5;
    while(dt.DayOfWeek == DayOfWeek.Saturday || dt.DayOfWeek == DayOfWeek.Sunday)
        dt = dt.AddDays(1);

    while (nDays-- > 0)
    {
        dt = dt.AddDays(1);
        if (dt.DayOfWeek == DayOfWeek.Saturday)
            dt = dt.AddDays(2);
    }
    return dt.AddDays(weeks*7);
}

答案 2 :(得分:4)

如果没有过度复杂的算法,你可以创建一个像这样的扩展方法:

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

答案 3 :(得分:4)

我会使用这个扩展名,记住,因为它是一个将它放在静态类中的扩展方法。

用法:

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

代码:

namespace ExtensionMethods
{
    public static class MyExtensionMethods
    {
        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;
        }
    }
}

答案 4 :(得分:3)

int daysToAdd = weekDaysToAdd + ((weekDaysToAdd / 5) * 2) + (((origDate.DOW + (weekDaysToAdd % 5)) >= 5) ? 2 : 0);

嗯要添加的“实际”天数是您指定的工作日数,加上该总数中的完整周数(因此为weekDaysToAdd / 5)乘以2(周末两天);如果一周中的原始日加上在一周内“添加”的工作日数(因此为weekDaysToAdd mod 5)大于或等于5(即周末日),则加上潜在的两天偏移。

注意:这可以假设0 =星期一,2 =星期二,... 6 =星期日。也;这对于工作日的负面间隔不起作用。

答案 5 :(得分:0)

我创建了一个扩展程序,允许您添加或减去工作日。 使用负数的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();
        }
    }
}

答案 6 :(得分:0)

如果有人在寻找TSQL解决方案,那就更好了。一行代码并使用底片。

CREATE FUNCTION[dbo].[AddBusinessDays](@Date date,@n INT)RETURNS DATE AS BEGIN 
DECLARE @d INT;SET @d=4-SIGN(@n)*(4-DATEPART(DW,@Date));
RETURN DATEADD(D,@n+((ABS(@n)+@d-2)/5)*2*SIGN(@n)-@d/7,@Date)END

答案 7 :(得分:0)

http://stackoverflow.com/questions/1044688答案的F#风格:

namespace FSharpBasics

module BusinessDays =

    open System;

    let private weekLength = 5

    (*operation*)
    let addBusinessDays (numberOfBusinessDays: int) (startDate: DateTime) =
        let startWeekDay = startDate.DayOfWeek
        let sign = Math.Sign(numberOfBusinessDays) 
        let weekendSlide, businessDaysSlide = 
            match startWeekDay with
            | DayOfWeek.Saturday when sign > 0 -> (2, -1)
            | DayOfWeek.Saturday when sign < 0 -> (-1, 1)   
            | DayOfWeek.Sunday when sign > 0 -> (1, -1)
            | DayOfWeek.Sunday when sign < 0 -> (-2, 1)
            | _ -> (0, 0)
        let baseStartDate = startDate.AddDays (float weekendSlide)        
        let days = Math.Abs (numberOfBusinessDays + businessDaysSlide) % weekLength
        let weeks = Math.Abs (numberOfBusinessDays + businessDaysSlide) / weekLength
        let baseWeekDay = int baseStartDate.DayOfWeek
        let oneMoreWeekend =
            if sign = 1 && days + baseWeekDay > 5 || sign = -1 && days >= baseWeekDay then 2
            else 0
        let totalDays = (weeks * 7) + days + oneMoreWeekend
        baseStartDate.AddDays (float totalDays)

    [<EntryPoint>]
    let main argv =
        let now = DateTime.Now 
        printfn "Now is %A" now
        printfn "13 business days from now would be %A" (addBusinessDays 13 now)
        System.Console.ReadLine() |> ignore
        0 

答案 8 :(得分:0)

这是我的方法。

我必须根据开始日期和天数来计算SLA(服务水平协议)的到期日期,并考虑到周末和公共假期:

    public DateTime? CalculateSLADueDate(DateTime slaStartDateUTC, double slaDays)
    {
        if (slaDays < 0)
        {
            return null;
        }

        var dayCount = slaDays;
        var dueDate = slaStartDateUTC;

        var blPublicHoliday = new PublicHoliday();
        IList<BusObj.PublicHoliday> publicHolidays = blPublicHoliday.SelectAll();

        do
        {
            dueDate = dueDate.AddDays(1);

            if ((dueDate.DayOfWeek != DayOfWeek.Saturday)
            && (dueDate.DayOfWeek != DayOfWeek.Sunday)
            && !publicHolidays.Any(x => x.HolidayDate == dueDate.Date))
            {
                dayCount--;
            }
        }
        while (dayCount > 0);

        return dueDate;
    }

blPublicHoliday.SelectAll()是公共假日的缓存内存列表。

(注意:这是用于公开共享的简化版本,有其非扩展方法的原因)

答案 9 :(得分:0)

enter code public static DateTime AddWorkDays(DateTime dt,int daysToAdd)
    {
        int temp = daysToAdd;
        DateTime endDateOri = dt.AddDays(daysToAdd);
        while (temp !=0)
        {
            if ((dt.AddDays(temp).DayOfWeek == DayOfWeek.Saturday)|| (dt.AddDays(temp).DayOfWeek == DayOfWeek.Sunday))
            {
                daysToAdd++;
                temp--;
            }
            else
            {
                temp--;
            }
        }
        while (endDateOri.AddDays(temp) != dt.AddDays(daysToAdd))
        {
            if ((dt.AddDays(temp).DayOfWeek == DayOfWeek.Saturday) || (dt.AddDays(temp).DayOfWeek == DayOfWeek.Sunday))
            {
                daysToAdd++;
            }
            temp++;
        }
        // final enddate check
        if (dt.AddDays(daysToAdd).DayOfWeek == DayOfWeek.Saturday)
        {
            daysToAdd = daysToAdd + 2;
        }
        else if (dt.AddDays(daysToAdd).DayOfWeek == DayOfWeek.Sunday)
        {
            daysToAdd++;
        }
        return dt.AddDays(daysToAdd);
    }

答案 10 :(得分:0)

DateTime oDate2 = DateTime.Now;

int days = 8;

for(int i = 1; i <= days; i++)
{
  if (oDate.DayOfWeek == DayOfWeek.Saturday) 
  {
    oDate = oDate.AddDays(2);
  }
  if (oDate.DayOfWeek == DayOfWeek.Sunday) 
  {
    oDate = oDate.AddDays(1);
  }
  oDate = oDate.AddDays(1);
}

答案 11 :(得分:-1)

公式为:工作日(日期,天数,(工作日(1)))

试试这个。这会有所帮助。

答案 12 :(得分:-2)

考虑到D年中原始日期的数量和W周的原始日期以及添加N的工作日数,下一个工作日数字为

W + N % 5.

一年中的第二天(没有环绕式检查)是

D + ((N / 5) * 7) + N % 5).

这假设你有整数除法。