2011-10-30 33 views
0

好吧,所以這應該是簡單的真的,但似乎我不能得到我的頭。 我有一張名爲Dates的表格,它列出了從2012年開始直到最後的所有日期。現在,當客戶進行預訂時,我需要獲取開始日期和結束日期,以日期時間格式生成它們之間的範圍,並根據表中的等效日期檢查每個日期以查看容量。如果是這樣,那麼通過預訂要求減少容量。 到目前爲止,我有這樣的代碼:C#比較日期然後遞減

private List<DateTime> getDateRange(DateTime startDate, DateTime endDate) 
{ 
     if (startDate > endDate) 
     { 
      return null; 
     } 
     List<DateTime> rv = new List<DateTime>(); 
     DateTime tmpDate = startDate; 
     do 
     { 
      rv.Add(tmpDate); 
      tmpDate = tmpDate.AddDays(1); 
     } while (tmpDate <= endDate); 
     return rv; 
    } 

的代碼應該產生在日期範圍列表,後來在這個函數被調用:

public void checkDateRange(DateTime startDate, DateTime endDate) 
{ 

     //need to check each element in the list against the table DateTest: 
     //changing the parameters of parse will give error. Require type handling 
     //First, extract the elements: 
     DateTime StartingDate = DateTime.Parse("02/25/2007"); 
     DateTime EndingDate = DateTime.Parse("03/06/2007"); 
     foreach (DateTime date in getDateRange(StartingDate, EndingDate)) 
     { 
      date.ToShortDateString(); 
     } 
      //rest of code should go here... 

} 

在想更像檢索整套表DateTest,然後在一個循環(不知道哪個)我會去檢查如果x = y這些是日期。任何代碼插圖將不勝感激。問候,

+1

你的問題是什麼? –

+0

我不確定如何執行此計劃,我需要將開始日期和結束日期之間的日期範圍與數據庫中的日期範圍進行比較。 –

+1

那麼...你有什麼問題?從數據庫中讀取?比較值?寫入數據庫? –

回答

1

我沒有看過你的代碼,但這裏有幾點意見:

  • 開始日期和結束日期之間的範圍是TimeSpan,而不是一個DateTime
  • 如果你有興趣在重建要麼StartDateEndDate,您可以添加或減去TimeSpan與其他價值
  • 如果您有興趣檢查重疊,那麼你有一個一維相交測試

這裏是如何做到一維相交測試:

One-Dimensional Line-Segments/Ranges Intersection Test: Solution Name?

bool intersects = !(
    (activity1.End < activity2.Begin) 
    || (activity2.End < activity1.Begin) 
    ); 

一旦你驗證,有兩個日期範圍之間的重疊,這裏是來計算重疊的方式:

DateTime end = activity1.End < activity2.End 
    ? activity1.End 
    : activity2.End; 

DateTime beginning = activity1.Begin > activity2.Begin 
    ? activity1.Begin 
    : activity2.Begin; 

有了這些檢查,我有一個潛在的解決方案。

潛在的解決方案

你可以讓一個特殊的數據結構,它不包含個人預約,而是包含了所有使用的容量。

當您爲此數據結構添加預留時,會檢查新值是否與現有預留重疊。您計算其所有現有值之間的交集。對於它重疊的每個值,只需將重疊部分添加到列表中,包括重疊處的當前預訂容量。

一旦計算完所有重疊,檢查列表中是否有任何項目已達到最大容量。如果他們有,那麼預訂是無效的,因爲它會讓你超過容量。如果他們沒有,您可以添加預訂。

要添加預訂,請將所有交叉點值的預訂計數加1。然後刪除預留範圍內數據結構中的所有現有值。如有必要拆分項目以僅刪除重疊部分。完成後,將增加的交叉點添加回列表中。

在刪除預訂時,您可以執行類似但相反的操作,但您必須將預訂合併到範圍的結尾/開始位置,而不是將其拆分。

或者,您可以用相反的方式對此進行建模,減去可用容量。哪一個對你更有意義。

該模型可以很好地用於建模可變容量,因爲您可以使用類似的數據結構爲容量建模。您只需在消耗的容量和可用容量之間進行額外的交叉測試,確保您始終有足夠的可用容量來滿足預定容量。

我會小心設計一個系統,這不是我所依賴的唯一數據,我可以從單獨的結構/表中的數據重新生成這些數據。例如,我將分別存儲每個預訂的開始和結束日期以及聯繫信息。

優化

您可以利用分類和空間分割算法的加快,你比較對所有預訂值的一部分。例如,您可以將所有值劃分爲長達一個月的區塊,因此您只需比較預訂相交的一兩個月。在關係數據庫中,這被稱爲時間分區。

如果您選擇分區,可以讓您的生活更簡單的一個要求是確保您的分區足夠大,以至於您只需要檢查兩個單元。使您的分區比這更小,並且您的算法會更加複雜,因此難以驗證。

如果您的數據足夠小,可以根據您感興趣的日期範圍即時計算整個表格,而不是將數據結構存儲在數據庫中。如果你的範圍足夠小以至於你可以在該範圍內每天檢查(或任何單位,如果你有不同的分辨率),你也可以不必擔心分區。這將允許您簡化一些操作,因爲您可以構建數據結構並進行容量檢查,而不必擔心分割或合併容量範圍等事情。

+0

嘿.. 。這是良好的部分我可以理解,但儘管如此,我認爲這是一個簡單的事情複雜化。這是一個良好的閱讀當然:) –

+0

@sys_debug:如果任何部分是特別混亂,或者你需要一些具體的例子,讓我知道什麼,在哪裏,我會看看我能解決它:) –

+0

我真正體會到了主動權Merlyn。很快我會在這裏發佈我的代碼。正如我所說的,我採用了一種簡單的解決方案,但您的帖子和下一篇文章當然必須參考何時使用permenant解決方案。如果您願意,請稍後再回來查看我的解決方案。我當然會欣賞有經驗的反饋。 –

2

基於對你想在這裏做什麼(總)的猜測:

public class Program 
{ 
    static void Main(string[] args) 
    { 
     TestDateRange(DateTime.Today, DateTime.Today.AddMonths(1)); 
    } 

    Dictionary<DateTime, List<string>> bookings; 
    int maxOccupancy = 2; 

    public Program(int year = 2011) 
    { 
     bookings = getDateRange(new DateTime(year, 1, 1), new DateTime(year,12,31)).ToDictionary(day => day, day => new List<string>()); 
    } 

    private static void TestDateRange(DateTime startDate, DateTime endDate) 
    { 
     Program p = new Program(); 

     if (p.GetFullDaysInDateRange(startDate, endDate).Count() == 0) 
     { 
      string bookingName = "Booking for test"; 
      p.AddBooking(startDate, endDate, bookingName); 
     } 
    } 

    private IEnumerable<DateTime> getDateRange(DateTime startDate, DateTime endDate) 
    { 
     if (startDate > endDate) 
     { 
      return null; 
     } 

     return Enumerable.Range((int)startDate.ToOADate(), endDate.Subtract(startDate).Days).Select(day => DateTime.FromOADate(day)); 
    } 

    private void AddBooking(DateTime startDate, DateTime endDate, string name) 
    { 
     IEnumerable<DateTime> range = getDateRange(startDate, endDate); 

     foreach (DateTime date in range) 
     { 
      if (bookings[date].Contains(name)) 
       return; //already placed this booking 

      if (bookings[date].Count > maxOccupancy) 
       throw new Exception(String.Format("Cannot book on {0}: full", date)); 

      bookings[date].Add(name); 
     } 
    } 

    public IEnumerable<DateTime> GetFullDaysInDateRange(DateTime startDate, DateTime endDate) 
    { 
     IEnumerable<DateTime> testRange = getDateRange(startDate, endDate); 
     List<DateTime> bookedDays = new List<DateTime>(); 

     foreach (DateTime date in testRange) 
     { 
      if (bookings[date].Count > maxOccupancy) 
       bookedDays.Add(date); 
     } 

     return bookedDays; 
    } 
} 
+1

+1,因爲這個答案更符合OP已經在做的事情。我的回答那種推土機推平,整個算法:)他們是邏輯上類似於無論如何,而你的是更簡單。 –

+0

我會用這個解決方案來快速和骯髒,而你的任何東西我需要維持超過幾周 – sq33G

+0

相當不錯,我必須說...謝謝你的努力...我仍然在看它 –