9


3

C#:特定の日付から就業日を追加する

これがうまくいかない。 特定の日に就業日を追加するメソッドを作成しています。 たとえば、2010年9月15日(水曜日)に3営業日を追加すると、メソッドは9月20日(来週月曜日)を返します。 土曜日と日曜日は無視されます。

C#でのこのようなもの:

DateTime AddWorkingDays(DateTime specificDate, int workingDaysToAdd)
{
   return specificDate + (workingDaysToAdd - (all saturdays and sundays))
}

私は計算に特別な休日を考慮していません。文字通り土曜日と日曜日を除く日を追加したいだけです。 前もって感謝します! =)

6 Answer


18


休日を考慮する必要がない場合は、次のようなことをお勧めします。

public static DateTime AddWorkingDays(DateTime specificDate,
                                      int workingDaysToAdd)
{
    int completeWeeks = workingDaysToAdd / 5;
    DateTime date = specificDate.AddDays(completeWeeks * 7);
    workingDaysToAdd = workingDaysToAdd % 5;
    for (int i = 0; i < workingDaysToAdd; i++)
    {
        date = date.AddDays(1);
        while (!IsWeekDay(date))
        {
            date = date.AddDays(1);
        }
    }
    return date;
}

private static bool IsWeekDay(DateTime date)
{
    DayOfWeek day = date.DayOfWeek;
    return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
}

それは非効率的ですが、理解しやすいです。 効率的なバージョンでは、以前と同様に追加する完全な週数を計算しますが、「現在の曜日」と「追加する残りの稼働日」から「追加する実際の日数」へのマッピングがあります。 次に、追加する合計日数を計算して、1回の呼び出しで実行できます。

編集:非効率のレベルの観点から…​ それは本当に悪いことではありません。 手動の「これは週末ですか」チェックのみを最大4日間実行しますが、それほど悪くはありません。 特に、イゴール(投稿時点で現在)の主張にもかかわらず、それは彼のアプローチよりも高速であり、ベンチマークにもかかわらず欠陥があります;)

まだ負の入力を処理できない可能性があることに注意してください-私はチェックしていません。

私が使用しているアプローチの背後にある理由の1つは、 `DayOfWeek`列挙型の値が何であるかを知っている私やコードリーダーに依存していないことです。 0-6、1-7、月曜日から日曜日、土曜日から金曜日かどうかは気にしません…​ または完全に奇妙な値がある場合でも。 等しいかどうかだけを比較します。これにより、コードは「明らかに正しく」なります。


1


クールな方法(と思う)は、次のような拡張メソッドに入れられます。

public static class DateTimeExtensions
{
    public static DateTime AddWorkingDays(this DateTime self, int days)
    {
        self = self.AddDays(days);
        while (self.DayOfWeek == DayOfWeek.Saturday || self.DayOfWeek == DayOfWeek.Sunday)
        {
            self = self.AddDays(1);
        }

        return self;
    }
}

最終コードは次のようになります。

specificDate.AddWorkingDays(3);


0


必要なものは次のとおりです。

更新しました :

public static DateTime AddWeekdays(DateTime start, int days)
    {
        int remainder = days % 5;
        int weekendDays = (days / 5) * 2;

        DateTime end = start.AddDays(remainder);

        if (start.DayOfWeek == DayOfWeek.Saturday && days > 0)
        {
            // fix for saturday.
            end = end.AddDays(-1);
        }

        if (end.DayOfWeek == DayOfWeek.Saturday && days > 0)
        {
            // add two days for landing on saturday
            end = end.AddDays(2);
        }
        else if (end.DayOfWeek < start.DayOfWeek)
        {
            // add two days for rounding the weekend
            end = end.AddDays(2);
        }

        // add the remaining days
        return end.AddDays(days + weekendDays - remainder);
    }


0


int foundWorkingDays = 0;
while (foundWorkingDays < workingDaysToAdd)
{
  specificDate= specificDate.AddDays(1);
  if(specificDate.DayOfWeek != DayOfWeek.Sunday && specificDate.DayOfWeek != DayOfWeek.Saturday)
     foundWorkingDays++;

}
return specificDate;

追加:

class Program
    {

        public static DateTime AddWorkingDays(DateTime specificDate,
                                      int workingDaysToAdd)
        {
            int completeWeeks = workingDaysToAdd / 5;
            DateTime date = specificDate.AddDays(completeWeeks * 7);
            workingDaysToAdd = workingDaysToAdd % 5;
            for (int i = 0; i < workingDaysToAdd; i++)
            {
                date = date.AddDays(1);
                while (!IsWeekDay(date))
                {
                    date = date.AddDays(1);
                }
            }
            return date;
        }

        private static bool IsWeekDay(DateTime date)
        {
            DayOfWeek day = date.DayOfWeek;
            return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
        }

        public static DateTime MyAddWorkingDays(DateTime specificDate,
                                      int workingDaysToAdd)
        {
            int foundWorkingDays = 0;
            while (foundWorkingDays < workingDaysToAdd)
            {
                specificDate = specificDate.AddDays(1);
                if (specificDate.DayOfWeek != DayOfWeek.Sunday && specificDate.DayOfWeek != DayOfWeek.Saturday)
                    foundWorkingDays++;

            }
            return specificDate;
        }


        static void Main(string[] args)
        {

            DateTime specificDate = DateTime.Now;

            Stopwatch globalTimer = Stopwatch.StartNew();
            Console.WriteLine(AddWorkingDays(specificDate, 300));  // 100000 :)
            globalTimer.Stop();
            Console.WriteLine(globalTimer.ElapsedMilliseconds);

            globalTimer = Stopwatch.StartNew();
            Console.WriteLine(MyAddWorkingDays(specificDate, 300)); // 100000 :)
            globalTimer.Stop();
            Console.WriteLine(globalTimer.ElapsedMilliseconds);



            Console.ReadLine();
        }
    }


0


古い投稿ですが、ネガティブな日も処理する拡張機能に興味を持つ人がいるかもしれません。 (@ジョンアンサーを作り直しました)

    public static DateTime AddWeekDays(this DateTime start, int days)
    {
        int direction = Math.Sign(days);

        int completeWeeks = days / 5;
        int remaining = days % 5;

        DateTime end = start.AddDays(completeWeeks * 7);

        for (int i = 0; i < remaining * direction; i++)
        {
            end = end.AddDays(direction * 1);
            while (!IsWeekDay(end))
            {
                end = end.AddDays(direction * 1);
            }
        }
        return end;
    }

    private static bool IsWeekDay(DateTime date)
    {
        DayOfWeek day = date.DayOfWeek;
        return day != DayOfWeek.Saturday && day != DayOfWeek.Sunday;
    }


0


これは私にとって最もきれいな方法のようです:

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

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

    return date;
}