日付と休日の一覧を指定して、この日に指定された稼働日数を追加するにはどうすればよいですか?休日を考慮しない小さな問題に対する多くの解決策があります(例えばAdding Days to a Date but Excluding Weekendsを参照)。週末と祝日を考慮して現在までの稼働日数を加算する
EDIT:O(1)または少なくともリニア(休日の数)のソリューションを探しています。
おかげ コンスタンチン
日付と休日の一覧を指定して、この日に指定された稼働日数を追加するにはどうすればよいですか?休日を考慮しない小さな問題に対する多くの解決策があります(例えばAdding Days to a Date but Excluding Weekendsを参照)。週末と祝日を考慮して現在までの稼働日数を加算する
EDIT:O(1)または少なくともリニア(休日の数)のソリューションを探しています。
おかげ コンスタンチン
......これを試してみてください助けてください初期化時間なし)
O(1)ソリューションが本当に必要な場合は、初期化の時間を考慮しないことをお勧めします。初期化するために
:
初期化コードとして日付で、あなただけの必要一度、結果をキャッシュします。
List<DateTime> validWorkdays = // ;
Dictionary<DateTime, int> lookupIndexOfValidWorkday = // ;
DateTime AddWorkdays(DateTime start, int count) {
var startIndex = lookupIndexOfValidWorkday[start];
return validWorkDays[startIndex + count];
}
Concerning the retrieve from the dictionary
を計算/クエリに
:
このプロパティの値を取得または設定はO(1)操作に近づきます。休日休日のリストを最新に最も古いものから選別されるという仮定の下で
の数に
O(N)。 (Credits for weekdays formula)
DateTime AddBusinessDay(DateTime start, int count, IEnumerable<DateTime> holidays) {
int daysToAdd = count + ((count/ 5) * 2) + ((((int)start.DayOfWeek + (count % 5)) >= 5) ? 2 : 0);
var end = start.AddDays(daysToAdd);
foreach(var dt in holidays) {
if (dt >= start && dt <= end) {
end = end.AddDays(1);
if (end.DayOfWeek == DayOfWeek.Saterday) {
end = end.AddDays(2);
}
}
}
return end;
}
この方法を最適化することができます。
リンク先の質問の回答のように、結果を計算するだけの簡単な数式を作成することは非常に難しいです。あなたが休日のために調整するとき、あなたの範囲に入る可能性のある新しい休日を考慮する必要があるので。週末には、それらの間に一定の間隔があることを知っています。 fromDateから+ GetNumberOfWorkDaysはtoDateまでが得られるはずです:コードの下
おそらくこのような何か
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace DateThing
{
class Program
{
static void Main(string[] args)
{
var holidays = new List<DateTime>()
{
new DateTime(2010, 12, 25),
new DateTime(2010, 12, 26)
};
var workDays = GetNumberOfWorkDays(DateTime.Today, new DateTime(2011, 1, 1), holidays);
}
static int GetNumberOfWorkDays(DateTime fromDate, DateTime toDate, ICollection<DateTime> holidays)
{
var days = 0;
for (var i = fromDate; i < toDate;)
{
if (i.DayOfWeek != DayOfWeek.Saturday && i.DayOfWeek != DayOfWeek.Sunday &&
(holidays != null && !holidays.Contains(i)))
days++;
i = i.AddDays(1);
}
return days;
}
}
}
を持っているなら、私に知らせてください。ありがとう。 – akonsu
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
namespace DateThing
{
class Program
{
static void Main(string[] args)
{
var holidays = new List<DateTime>()
{
new DateTime(2010, 12, 25),
new DateTime(2010, 12, 26)
};
var futureDate = CalculateFutureDate(DateTime.Today, 20, holidays);
}
static DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
var futureDate = fromDate;
for (var i = 0; i < numberofWorkDays; i++)
{
if (futureDate.DayOfWeek == DayOfWeek.Saturday || futureDate.DayOfWeek == DayOfWeek.Sunday ||
(holidays != null && holidays.Contains(futureDate)))
futureDate = futureDate.AddDays(1); // Increase FutureDate by one because of condition
futureDate = futureDate.AddDays(1); // Add a working day
}
return futureDate;
}
}
}
私は私が探しているものを明確にするために私の質問を編集しました。 – akonsu
「if」ではなく「while」が必要なのでしょうか?土曜日 - 日曜日 - 休日の組み合わせをスキップする。 –
は((1)Oに近づいて
private DateTime CalculateFutureDate(DateTime fromDate, int numberofWorkDays, ICollection<DateTime> holidays)
{
var futureDate = fromDate;
var daterange = Enumerable.Range(1, numberofWorkDays * 2);
var dateSet = daterange.Select (d => futureDate.AddDays(d));
var dateSetElim = dateSet.Except(holidays).Except(dateSet.Where(s =>s.DayOfWeek == DayOfWeek.Sunday).Except(dateSet.Where (s=>s.DayOfWeek==DayOfWeek.Saturday)));
//zero-based array
futureDate = dateSetElim.ElementAt(numberofWorkDays-1);
return futureDate;
}
//が動作している...あなたは、私は逆ない方法を探しています任意の懸念
DateTime AddBusinessDays(int noofDays, DateTime dtCurrent)
{
var holidays = new List<DateTime>() { new DateTime(2013, 10, 22), new DateTime(2013, 10, 28)};
DateTime tempdt = new DateTime(dtCurrent.Year, dtCurrent.Month, dtCurrent.Day);
// if starting day is non working day adjust to next working day
tempdt = ExcludeNotWorkingDay(tempdt, holidays);
// if starting day is non working day adjust to next working day then minus 1 day in noofadding days
if (tempdt.Date > dtCurrent.Date && !(noofDays == 0))
noofDays = noofDays - 1;
while (noofDays > 0)
{
tempdt = tempdt.AddDays(1);
// if day is non working day adjust to next working day
tempdt = ExcludeNotWorkingDay(tempdt, holidays);
noofDays = noofDays - 1;
}
return tempdt;
}
DateTime ExcludeNotWorkingDay(DateTime dtCurrent, List<DateTime> holidays)
{
while (!IsWorkDay(dtCurrent, holidays))
{
dtCurrent = dtCurrent.AddDays(1);
}
return dtCurrent;
}
bool IsWorkDay(DateTime dtCurrent, List<DateTime> holidays)
{
if ((dtCurrent.DayOfWeek == DayOfWeek.Saturday || dtCurrent.DayOfWeek == DayOfWeek.Sunday ||
holidays.Contains(dtCurrent)))
{
return false;
}
else
{
return true;
}
}
O(n)ソリューションにはバグがあります。調整した後、新しい終了日が週末になるかどうかを確認する必要があります。 – akonsu
はい、それについては考えていませんでした。 – GvS
DayOfWeekをO(n)ソリューションにキャストする必要はありません: (int)start.DayOfWeek – Tr1stan