Добавление дней к дате, но исключая выходные - PullRequest
23 голосов
/ 11 ноября 2008

Учитывая дату, как я могу добавить к ней количество дней, но исключить выходные. Например, если указать 12.12.2008 (среда) и добавить пять, то получится 19.11.2008 (среда), а не 17.11.2008 (понедельник).

Я могу придумать простое решение, такое как циклическое добавление каждого дня и проверка на выходных, но хотелось бы посмотреть, есть ли что-нибудь более элегантное. Я также был бы заинтересован в любом решении F #.

Ответы [ 10 ]

16 голосов
/ 04 сентября 2009

с использованием Fluent DateTime https://github.com/FluentDateTime/FluentDateTime

var dateTime = DateTime.Now.AddBusinessDays(4);
6 голосов
/ 11 ноября 2008
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);
}
4 голосов
/ 14 июня 2016

Я бы использовал это расширение, помните, поскольку это метод расширения для помещения его в статический класс.

Использование:

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 голосов
/ 10 июня 2016

Не усложняя алгоритм, вы можете просто создать метод расширения, подобный этому:

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 голосов
/ 11 ноября 2008
int daysToAdd = weekDaysToAdd + ((weekDaysToAdd / 5) * 2) + (((origDate.DOW + (weekDaysToAdd % 5)) >= 5) ? 2 : 0);

Для остроумия; количество «настоящих» дней, которые нужно добавить, - это количество дней недели, которые вы указываете, плюс количество полных недель в этом общем количестве (следовательно, weekDaysToAdd / 5) раз два (два дня в выходные); плюс потенциальное смещение в два дня, если исходный день недели плюс количество будних дней для добавления «в пределах» недели (следовательно, weekDaysToAdd mod 5) больше или равно 5 (т. е. является выходным днем).

Примечание: это работает при условии, что 0 = понедельник, 2 = вторник, ... 6 = воскресенье. Также; это не работает на отрицательных рабочих днях.

0 голосов
/ 20 мая 2018

F # аромат http://stackoverflow.com/questions/1044688 ответа:

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 
0 голосов
/ 13 февраля 2014

Это лучше, если кто-то ищет решение 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
0 голосов
/ 06 августа 2013

Я создал расширение, которое позволяет вам добавлять или вычитать рабочие дни. Используйте отрицательное количество 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();
        }
    }
}
0 голосов
/ 24 сентября 2009

Формула будет: Рабочий день (дата, число дней, (день недели (1)))

Попробуй это. Это поможет.

0 голосов
/ 11 ноября 2008

Учитывая номер исходного дня в году D и исходного дня в неделе W и количество рабочих дней, которые нужно добавить N, номер следующего дня недели будет

W + N % 5.

На следующий день в году (без проверки с циклом)

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

Предполагается, что у вас целочисленное деление.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...