2010-12-08 11 views
1

日付と休日の一覧を指定して、この日に指定された稼働日数を追加するにはどうすればよいですか?休日を考慮しない小さな問題に対する多くの解決策があります(例えばAdding Days to a Date but Excluding Weekendsを参照)。週末と祝日を考慮して現在までの稼働日数を加算する

EDIT:O(1)または少なくともリニア(休日の数)のソリューションを探しています。

おかげ コンスタンチン

答えて

1

......これを試してみてください助けてください初期化時間なし)

O(1)ソリューションが本当に必要な場合は、初期化の時間を考慮しないことをお勧めします。初期化するために

  • ビルドは、有効な戻り値です照会可能な範囲内のすべての日付のリストを並べ替え。
  • 上記リストから日付のビルドハッシュテーブル(のRikガーナーからの回答のコードのようなものを使用して)、値として、リスト内のキー、インデックス

初期化コードとして日付で、あなただけの必要一度、結果をキャッシュします。

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までが得られるはずです:コードの下

+1

O(n)ソリューションにはバグがあります。調整した後、新しい終了日が週末になるかどうかを確認する必要があります。 – akonsu

+0

はい、それについては考えていませんでした。 – GvS

+0

DayOfWeekをO(n)ソリューションにキャストする必要はありません: (int)start.DayOfWeek – Tr1stan

-1

おそらくこのような何か

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


} 
+0

を持っているなら、私に知らせてください。ありがとう。 – akonsu

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

私は私が探しているものを明確にするために私の質問を編集しました。 – akonsu

+2

「if」ではなく「while」が必要なのでしょうか?土曜日 - 日曜日 - 休日の組み合わせをスキップする。 –

0

は((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; 
    } 
+0

ありがとうございます。休日の集まりにfromDateから始まるnumberofWorkDays * 2休暇が並んでいるとします。 – akonsu

+0

範囲内の値を調整できます。コードで私はこれを取得しました。私たちは常に多くの就業日、すなわちnumberOfWorkDays >> holidays [fromとto]を追加しています。あなたのケースでは(numberOfWorkDays * 2)+ holidays.Countおそらくすることができますか? – Rikalous

0

//が動作している...あなたは、私は逆ない方法を探しています任意の懸念

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; 
     } 
    } 
関連する問題