2010-08-25 53 views
1

簡單的問題。我有一個有序的日期集合。他們是英國BTW日期查找日期範圍從日期集合C#

01/01/10 
01/02/10 
01/03/10 
01/04/10 
02/04/10 
03/04/10 
04/04/10 

而且我想這個轉換成日期的集合範圍

01/01/10 -> 01/01/10 
01/02/10 -> 01/02/10 
01/03/10 -> 01/03/10 
01/04/10 -> 04/04/10 

只是爲了澄清,我想任何連續的日期轉換成一個範圍。所以前3個日期是獨立的,最後4個日期轉換爲4月1日至4月4日的範圍。

現在我可以使用循環做到這一點,但它不是很優雅。有沒有人有任何解決方案?

感謝

+0

這些日期的地區是什麼? 「01/02/10」可能是2010年2月1日或2010年1月1日(甚至可能是2001年2月10日?),具體取決於它們代表的區域設置。因爲我們正在談論範圍和排序,這有所作爲。 – 2010-08-25 08:44:42

+0

他們是英國的格式;) – 2010-08-25 08:48:37

+0

它可能只是咖啡不足,但我不能推斷從這些日期生產這些範圍的規則。你能澄清嗎? – AakashM 2010-08-25 08:52:32

回答

5

既然你要確定連續日期範圍的範圍,我認爲你唯一的選擇是,像你說的一環。您可以在單次做到這一點,雖然,並把它放在一個擴展方法,以便它會在任何IList<DateTime>操作,例如:

// purely an example, chances are this will have actual, y'know logic in live 
public class DateRange 
{ 
    private List<DateTime> dates = new List<DateTime>(); 

    public void Add(DateTime date) 
    { 
     this.dates.Add(date); 
    } 

    public IEnumerable<DateTime> Dates 
    { 
     get { return this.dates; } 
    } 
} 

public static IEnumerable<DateRange> GetRanges(this IList<DateTime> dates) 
{ 
    List<DateRange> ranges = new List<DateRange>(); 
    DateRange currentRange = null; 

    // this presumes a list of dates ordered by day, if not then the list will need sorting first 
    for(int i = 0; i < dates.Count; ++i) 
    { 
     var currentDate = dates[i]; 
     if(i == 0 || dates[i - 1] != currentDate.AddDays(-1)) 
     { 
      // it's either the first date or the current date isn't consecutive to the previous so a new range is needed 
      currentRange = new DateRange(); 
      ranges.Add(currentRange); 
     } 

     currentRange.Add(currentDate); 
    } 

    return ranges; 
} 

你也可以將它通過傳遞一個IEnumerable<DateTime>更加通用:

public static IEnumerable<DateRange> GetRanges(this IEnumerable<DateTime> dates) 
{ 
    List<DateRange> ranges = new List<DateRange>(); 
    DateRange currentRange = null; 
    DateTime? previousDate = null; 

    // this presumes a list of dates ordered by day, if not then the list will need sorting first 
    foreach(var currentDate in dates) 
    { 
     if(previousDate == null || previousDate.Value != currentDate.AddDays(-1)) 
     { 
      // it's either the first date or the current date isn't consecutive to the previous so a new range is needed 
      currentRange = new DateRange(); 
      ranges.Add(currentRange); 
     } 

     currentRange.Add(currentDate); 
     previousDate = currentDate; 
    } 

    return ranges; 
} 
+0

雖然這將解決這種情況下的問題。我不想按月分組日期,而是計算日期連續的日期範圍。 – 2010-08-25 08:57:14

+0

啊,我已經編輯了我的答案。 – 2010-08-25 09:18:31

+0

AM我認爲這需要訂購日期嗎?看起來它會起作用,但是想知道是否值得在開始時進行排序(可能用一個bool參數來告訴它是否需要排序),以便它能夠處理無序的日期範圍。 – Chris 2010-08-25 09:47:35

0
var stringDates = new List<string> {"01/09/10", "31/08/10", "01/01/10"}; 

var dates = stringDates.ConvertAll(DateTime.Parse); 
dates.Sort(); 

var lastDateInSequence = new DateTime(); 
var firstDateInSequence = new DateTime(); 

foreach (var range in dates.GroupBy(
    d => { if ((d - lastDateInSequence).TotalDays != 1) 
       firstDateInSequence = d; 
      lastDateInSequence = d; 
      return firstDateInSequence; 
     })) 
    { 
     var sb = new StringBuilder(); 
     sb.Append(range.First().ToShortDateString()); 
     sb.Append(" => "); 
     sb.Append(range.Last().ToShortDateString()); 
     Console.WriteLine(sb.ToString()); 
    } 
0
dates.Aggregate(new List<DateRange>(), (acc, dt) => 
             { 
             if (acc.Count > 0 && acc.Last().d2 == dt.AddDays(-1)) 
              acc[acc.Count - 1].d2 = dt; 
             else 
              acc.Add(new DateRange(dt, dt)); 
             return acc; 
             } 
    ); 

其中DateRange是一類這樣的:

class DateRange 
{ 
    public DateTime d1, d2; 

    public DateRange(DateTime d1, DateTime d2) 
    { 
    this.d1 = d1; 
    this.d2 = d2; 
    } 
}