2010-09-15 44 views
8

我無法做到這一點。我正在創建一個在特定日期添加工作日的方法。例如,我想在2010年9月15日(星期三)增加3個工作日,該方法將於9月20日(下週一)返回。它無視週六和週日,因爲它的非工作日..C#:從cetain日期添加工作日

像這樣的東西在C#:

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

我不認爲在計算特殊的節日,我只是從字面上要添加天週六除外和星期日..在此先感謝! =)

回答

16

如果你不需要考慮假期,我會建議你做這樣的事情:

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

這是效率低下,而且容易理解。對於高效版本,您可以像以前一樣計算完整週的數量,但是可以將任何「當前的一週中的某天」和「剩餘的工作日」添加到「實際的天數」映射到加」。然後,您可以計算出要添加的總天數,並在一次調用中完成。

編輯:無效率的水平...它真的不是非常不好。它只會執行手動「這是一個週末」檢查長達4天,這不算太糟糕。尤其是,儘管igor(目前在發佈時間)聲稱,它比他的方法更快,儘管有缺陷的基準;)

請注意,它可能無法處理負面輸入 - 我沒有檢查。

我使用的方法背後的原因之一是它不依賴於我或代碼閱讀器知道DayOfWeek枚舉值是什麼。我不在乎它是0-6,1-7,星期一 - 星期日,星期六 - 星期五......還是即使有完全離奇的價值。我只比較平等,這使代碼更「明顯正確」。

+0

喬恩,這將是更有效地使用'workingDaysToAdd = workingDaysToAdd 5%; date = date.AddDays(workingDaysToAdd); if(date.DayOfWeek == DayOfWeek.Saturday)date.AddDays(2); if(date.DayOfWeek == DayOfWeek.Sunday)date.AddDays(1);'而不是循環結構?只是好奇。 – Lazarus 2010-09-15 13:11:36

+0

我測試了它,它對我確切需要的東西有效。你在飛行中做過嗎?在我發佈後不到5分鐘..人,這是相當真棒..但我會歡迎更有效的答案..謝謝btw .. – CSharpNoob 2010-09-15 13:15:00

+1

我不會說這是低效的,但所有的事情都是相對的。答案佔預計數週,因此最多需要循環6次(工作日%5最多4次,週末最多2次)。不是一個巨大的打擊。 – 2010-09-15 13:17:49

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

但是datetime參數(start)也可以是星期日和星期六.. :(..如果星期六和星期日,它必須返回下週星期三, – CSharpNoob 2010-09-15 13:17:55

+0

我剛剛編輯了你要做的事 – 2010-09-15 13:53:59

+0

不是嗎?有點太複雜了?我認爲這可以用更簡單的方式完成 – tocqueville 2016-06-10 11:48:35

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

它比先生更有效率嗎? Jon Skeet的建議? – CSharpNoob 2010-09-15 13:22:19

+0

@CSharpNoob,no。這基本上是相同的邏輯,沒有處理整個星期前。因此,不是一個循環可以從1到4(加上兩個週末),你有一個從1到* n *(加上*所有*週末日)的循環 – 2010-09-15 13:31:30

+0

MyAddWorkingDays和AddWorkingDays之間的區別是什麼在你的代碼? – CSharpNoob 2010-09-15 13:41:30

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

即使我經過2天或更多天,它也只會增加一天.. – CSharpNoob 2010-09-15 13:33:59

+0

正如CSharpNoob指出的,這段代碼並不能正常工作,但我真的很喜歡爲此使用擴展方法的方法。 – Patrick 2010-09-15 13:40:04

+0

是的,它錯了,之前我沒有很好的測試。對不起,我的錯。 – 2010-09-15 15:53:51

-1

是一個老的文章,但有人可能有意,也負責處理負面天的延期。(我返工@喬恩答案)

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