2010-08-25 30 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; 
    } 
}