[英]Adding Days to a Date but Excluding Weekends
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# 解决方案感兴趣。
使用 Fluent DateTime https://github.com/FluentDateTime/FluentDateTime
var dateTime = DateTime.Now.AddBusinessDays(4);
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);
}
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;
}
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);
要添加的“实际”天数是您指定的工作日数,加上该总数中的完整周数(因此为 weekDaysToAdd / 5)乘以 2(周末两天); 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 (ie is a weekend day).
如果一周中的原始日期加上一周“内”添加的工作日数(因此 weekDaysToAdd mod 5)大于或等于 5(即是周末日),则加上两天的潜在偏移量。
Note: this works assuming that 0 = Monday, 2 = Tuesday, ... 6 = Sunday.注意:这假设 0 = 星期一,2 = 星期二,... 6 = 星期日。 Also;
还; this does not work on negative weekday intervals.
这不适用于负的工作日间隔。
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;
}
}
}
Source:来源:
https://github.com/FluentDateTime/FluentDateTime/blob/master/src/FluentDateTime/DateTime/DateTimeExtensions.cs https://github.com/FluentDateTime/FluentDateTime/blob/master/src/FluentDateTime/DateTime/DateTimeExtensions.cs
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();
}
}
}
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
This is better if anyone is looking for a TSQL
solution.如果有人正在寻找
TSQL
解决方案,这会更好。 One line of code and works with negatives.一行代码并处理底片。
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
Here is how I did it.这是我如何做到的。
I had to calculate SLA (Service Level Agreement) due dates based on a start date and number of days, and account for weekends and public holidays:我必须根据开始日期和天数计算 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() is a cached in-memory list of public holidays. blPublicHoliday.SelectAll() 是一个缓存在内存中的公共假期列表。
(note: this is a cut down version for sharing publicly, there is a reason its not an extension method) (注意:这是公开共享的缩减版本,它不是扩展方法是有原因的)
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);
}
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);
}
Formula will be: Workday(date,no.of days,(weekday(1)))公式为:工作日(日期,天数,(工作日(1)))
Try this.尝试这个。 This will help.
这会有所帮助。
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.这是假设您有整数除法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.