C# 向日期添加天数但不包括周末

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/279296/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 21:20:50  来源:igfitidea点击:

Adding Days to a Date but Excluding Weekends

c#f#date

提问by Bob

Given a date how can I add a number of days to it, but exclude weekends. For example, given 11/12/2008 (Wednesday) and adding five will result in 11/19/2008 (Wednesday) rather than 11/17/2008 (Monday).

给定一个日期,我如何为其添加天数,但不包括周末。例如,给定 11/12/2008(星期三)并添加五个将导致 11/19/2008(星期三)而不是 11/17/2008(星期一)。

I can think of a simple solution like looping through each day to add and checking to see if it is a weekend, but I'd like to see if there is something more elegant. I'd also be interested in any F# solution.

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

采纳答案by Simon

using Fluent DateTime https://github.com/FluentDateTime/FluentDateTime

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

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

回答by gnud

Given the number of the original day in the year D and original day in the week W and the number of workdays to add N, the next weekday number is

给定 D 年的原始天数和 W 周的原始天数,加上 N 的工作日数,下一个工作日数为

W + N % 5.

The next day in the year (with no wraparound check) is

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

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

This is assuming that you have integer division.

这是假设您有整数除法。

回答by LeppyR64

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

回答by Paul Sonier

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

To wit; the number of "real" days to add is the number of weekdays you're specifying, plus the number of complete weeks that are in that total (hence the weekDaysToAdd / 5) times two (two days in the weekend); plus a potential offset of two days if the original day of the week plus the number of weekdays to add "within" the week (hence the weekDaysToAdd mod 5) is greater than or equal to 5 (i.e. is a weekend day).

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

Note: this works assuming that 0 = Monday, 2 = Tuesday, ... 6 = Sunday. Also; this does not work on negative weekday intervals.

注意:这假设 0 = 星期一,2 = 星期二,... 6 = 星期日。还; 这不适用于负的工作日间隔。

回答by Simon

Formula will be: Workday(date,no.of days,(weekday(1)))

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

Try this. This will help.

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

回答by Arjen

I created an extension that allows you to add or subtract business days. Use a negative number of businessDays to subtract. It seems to work in all cases.

我创建了一个扩展程序,允许您增加或减少工作日。使用负数的工作日来减去。它似乎适用于所有情况。

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

Example:

例子:

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

回答by ElmerMiller

This is better if anyone is looking for a TSQLsolution. One line of code and works with negatives.

如果有人正在寻找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

回答by tocqueville

Without over-complicating the algorithm, you could just create an extension method like this:

在不使算法过于复杂的情况下,您可以创建一个像这样的扩展方法:

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

回答by Ogglas

I would use this extension, remember since it is an extension method to put it in a static class.

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

Usage:

用法:

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

Code:

代码:

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

回答by Ogglas

F# flavor of http://stackoverflow.com/questions/1044688's answer:

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