2010-01-13 72 views
0

我需要創建一個函數來返回給定項目的下一個處理日期。一個項目有一個數字,表示處理它的一個季度內的月份,以及一個數字,表示該月處理該月的那一週。因此,給定特定項目的創建日期,我需要獲取該項目的下一個處理日期,這將是第一天在四分之一內分配的周和月。在一個季度內獲取下一個日期

請注意,無論一週中的哪一天,本週開始7天都會突破數週。因此,第一週的第一天可能會在週二或其他任何一天開始計算。

例如:
比方說,我有一個完成日期爲2010年1月8日的項目。該項目的monthWithinQuarter值爲2.它的weekWithinMonth值爲3.因此,對於此項目可以解決爲2月的第三週,所以我希望該函數返回2010年2月15日的日期。

的功能應該是這個樣子:

var nextProcessingDate = GetNextProcessingDate(
          itemCompletedDate, 
          monthWithinQuarter, 
          weekWithinMonth); 

這種計算必須是非常快的,這一計算將要發生的事情很多,無論是在實時顯示在網站上,以及在批處理模式下處理項目。

感謝,

〜賈斯汀

+0

減少什麼是GetNextProcessingDate(新的DateTime(的'結果2010,3,31),3,1)'?假設'3/31/2010'是第一季度的最後一天,我沒有看到如果沒有提供進一步的說明,你會如何解決這個問題。 – jason 2010-01-13 16:05:52

+0

詢問下一個日期是3/31,第3個月和第1周應該是2010年6月1日。這是該項目的下一個可用處理日期。 2010年3月1日已通過,因此無法使用。 – RationalGeek 2010-01-13 16:19:08

+0

好的,那麼我認爲我目前的版本應該爲你做這項工作。 – jason 2010-01-13 16:53:29

回答

0

好吧,這應該爲你做:

static DateTime GetNextProcessingDate(
    DateTime itemCompletedDate, 
    int monthWithinQuarter, 
    int weekWithinMonth 
) { 
     if (monthWithinQuarter < 1 || monthWithinQuarter > 3) { 
      throw new ArgumentOutOfRangeException("monthWithinQuarter"); 
     } 
     if (weekWithinMonth < 1 || weekWithinMonth > 5) { 
      throw new ArgumentOutOfRangeException("weekWithinMonth"); 
     } 
     int year = itemCompletedDate.Year; 
     DateTime[] startOfQuarters = new[] { 
      new DateTime(year, 1, 1), 
      new DateTime(year, 4, 1), 
      new DateTime(year, 7, 1), 
      new DateTime(year, 10, 1) 
     }; 
     DateTime startOfQuarter = startOfQuarters.Where(d => d <= itemCompletedDate) 
               .OrderBy(d => d) 
               .Last(); 
     int month = startOfQuarter.Month + monthWithinQuarter - 1; 
     int day = (weekWithinMonth - 1) * 7 + 1; 
     if (day > DateTime.DaysInMonth(year, month)) { 
      throw new ArgumentOutOfRangeException("weekWithinMonth"); 
     } 
     DateTime candidate = new DateTime(year, month, day); 
     if (candidate < itemCompletedDate) { 
      month += 3; 
      if(month > 12) { 
       year++; 
       month -= 12; 
      } 
     } 
     return new DateTime(year, month, day); 
    } 

至於效率,在這裏我看到的最改進的餘地反覆創建陣列

DateTime[] startOfQuarters = new[] { 
    new DateTime(year, 1, 1), 
    new DateTime(year, 4, 1), 
    new DateTime(year, 7, 1), 
    new DateTime(year, 10, 1) 
}; 

讓我們卸載的地方以一種方法和記憶它:

static Dictionary<int, DateTime[]> cache = new Dictionary<int, DateTime[]>(); 
public static DateTime[] StartOfQuarters(DateTime date) { 
    int year = date.Year; 
    DateTime[] startOfQuarters; 
    if(!cache.TryGetValue(year, out startOfQuarters)) { 
     startOfQuarters = new[] { 
      new DateTime(year, 1, 1), 
      new DateTime(year, 4, 1), 
      new DateTime(year, 7, 1), 
      new DateTime(year, 10, 1) 
     }; 
     cache.Add(year, startOfQuarters); 
    } 
    return startOfQuarters; 
} 

如果你不需要宿舍的靈活性可能開始於不尋常的日子裏,你可以取代

DateTime[] startOfQuarters = new[] { 
    new DateTime(year, 1, 1), 
    new DateTime(year, 4, 1), 
    new DateTime(year, 7, 1), 
    new DateTime(year, 10, 1) 
}; 
DateTime startOfQuarter = startOfQuarters.Where(d => d <= itemCompletedDate).OrderBy(d => d).Last(); 
int month = startOfQuarter.Month + monthWithinQuarter - 1; 

int month = 3 * ((itemCompletedDate.Month - 1)/3) + monthWithinQuarter; 
+0

與我的解決方案非常相似,在大多數地方......檢測季度的方法可能是矯枉過正或OP想要的。無法確定當前的信息。 – Noldorin 2010-01-13 16:28:16

+0

是的,這取決於。我來自一個季度開始的世界通常不是'1/1','4/1','7/1','10/1',所以我總是準備好他們沒有的可能性。 – jason 2010-01-13 16:29:59

+0

@Downvoter:請解釋。 – jason 2010-01-13 16:44:24

-1

據我所知,這應該做的工作:

public static DateTime GetNextProcessingDate(DateTime itemCreationDate, int monthWithinQuarter, 
    int weekWithinMonth) 
{ 
    var quarter = (itemCreationDate.Month - 1)/4; // Assumes quarters are divided by calendar year. 
    var month = quarter * 4 + monthWithinQuarter; // First quarter of month plus month within quarter 
    var dayInMonth = (weekWithinMonth - 1) * 7 + 1; // Weeks are counted from first day, regardless of day of week (as you mention). 
    return new DateTime(itemCreationDate.Year, month, dayInMonth); 
} 

讓我知道,如果它的任何不明確。

+0

這不適用於'itemCreationDate = new DateTime(2010,3,31),monthWithinQuarter = 3'和'weekWithinMonth = 1'。 – jason 2010-01-13 16:31:39

+0

這也不適用於'itemCreationDate = new DateTime(2010,1,1),monthWithinQuarter = 1和weekWithinMonth = 1'。 – jason 2010-01-13 16:39:39

+0

@Jason。當然可以。我不明白爲什麼不......這真的值得投票嗎? – Noldorin 2010-01-13 16:40:01

-2

你的計算,我想應該在

DateTime dt; 
    dt.AddDays(daysToAdd); 
    dt.AddMonths(monthsToAdd); 
    dt.AddHours(hoursToAdd); 
    dt.AddYears(yearsToAdd); 
相關問題