2010-08-02 67 views
8

我正在尝试为两个DateTime变量之间的DateTime集合找到缺失的日期。查找给定范围的缺失日期

例如。

Collection 
2010-01-01 
2010-01-02 
2010-01-03 
2010-01-05 

DateRange 
2010-01-01 -> 2010-01-06 

会给我

2010-01-04 
2010-01-06 

我能想到的几个的List<DateTime>的是实现这个的,但没有干净和简单

任何想法?

回答

16

我想了很多,实施这个办法,例如:

DateTime[] col = { new DateTime(2010, 1, 1), 
        new DateTime(2010, 1, 2), 
        new DateTime(2010, 1, 3), 
        new DateTime(2010, 1, 5)}; 

var start = new DateTime(2010, 1, 1); 
var end = new DateTime(2010, 1, 6); 

var range = Enumerable.Range(0, (int)(end - start).TotalDays + 1) 
         .Select(i => start.AddDays(i)); 

var missing = range.Except(col); 

而且你可以把范围,塞给她一个扩展法

public static class extensions 
{ 
    public static IEnumerable<DateTime> Range(this DateTime startDate, DateTime endDate) 
    { 
     return Enumerable.Range(0, (int)(endDate - startDate).TotalDays + 1) 
         .Select(i => startDate.AddDays(i)); 
    } 
} 

那么它会简单地

DateTime[] col = { new DateTime(2010, 1, 1), 
        new DateTime(2010, 1, 2), 
        new DateTime(2010, 1, 3), 
        new DateTime(2010, 1, 5)}; 

var start = new DateTime(2010, 1, 1); 
var end = new DateTime(2010, 1, 6); 
var missing = start.Range(end).Except(col); 

但也许这并不是一个高性能的解决方案:-)

+0

这与我的想法类似,除了使用for循环来建立我的范围。我只是不喜欢每次建立一个日子清单的想法,因为我必须做很多安静的事情。 – 2010-08-02 14:05:25

+1

+1很好的使用范围。 – Thomas 2010-08-02 14:05:26

+0

是的,巧妙的使用范围;) – 2010-08-02 14:07:59

2

具体取决于您要查找的内容以及数据集的大小。一个简单的方法是将日期加载到一个集合中,然后使用一个简单的循环。我会在第二秒添加一个代码示例。

DateTime currentDate = new DateTime(2010, 1, 1); 
DateTime endDate = new DateTime(2010, 1, 6); 
List<DateTime> existingDates = new List<DateTime>; //You fill with values 
List<DateTime> missingDates = new List<DateTime>; 

while(currentDate <= endDate) 
{ 
    if(existingDates.contains(currentDate)) 
     missingDates.Add(currentDate); 

    //Increment date 
    currentDate = currentDate.AddDays(1); 
} 

使用这个例子中,你只需要加载“existingDates”用正确的价值观,那么“missingDates”名单将有你的结果

+0

是否使用。载有(..)有没有好的办法?将整个数组与整个迭代中的一个项匹配。我没有进行基准测试,但是我会去找一个Where和Count命中<1的地方。 – Independent 2011-09-16 15:26:50

1
var dates = new List<DateTime> 
       { 
        new DateTime(2010, 01, 01), 
        new DateTime(2010, 01, 02), 
        new DateTime(2010, 01, 03), 
        new DateTime(2010, 01, 05) 
       }; 

var targetDate = new DateTime(2010, 01, 01); 

var missingDates = new List<DateTime>(); 
while (targetDate <= new DateTime(2010, 01, 06)) 
{ 
    if (!dates.Contains(targetDate)) 
     missingDates.Add(targetDate); 

    targetDate = targetDate.AddDays(1); 
} 

foreach (var date in missingDates) 
    Debug.WriteLine(date.ToString()); 

如果你想解决这个LINQ的,我不相信这是可能的,除非你也有最低和最高日期之间的所有日期列表。在SQL中,这相当于一个包含给定时间段内所有日期的日历表。

这里是一个LINQ的解决方案,我创建日历列表​​我上面再提到查询失踪日期:

var dates = new List<DateTime> 
       { 
        new DateTime(2010, 01, 01), 
        new DateTime(2010, 01, 02), 
        new DateTime(2010, 01, 03), 
        new DateTime(2010, 01, 05) 
       }; 
var calendar = new List<DateTime>(); 
var targetDate = new DateTime(2010, 01, 01); 
while (targetDate <= new DateTime(2010, 01, 06)) 
{ 
    calendar.Add(targetDate); 
    targetDate = targetDate.AddDays(1); 
} 

var missingDates = (from date in calendar 
       where !dates.Contains(date) 
       select date).ToList(); 

foreach (var date in missingDates) 
    Debug.WriteLine(date.ToString()); 
1

懒惰评估辅助方法,有助于生成日期与比较的列表。可能想要为大型集合评估此方法。

void Main() 
{ 
    var dates = new[] {new DateTime(2000,1,1), new DateTime(2000,1,5)}; 
    DateHelper.Range(new DateTime(2000,1,1), new DateTime(2000,1,5)).Except(dates).Dump(); 
} 

// Define other methods and classes here 
public static class DateHelper { 
    public static IEnumerable<DateTime> Range(DateTime start, DateTime end) { 
     var days = end.Subtract(start).Days; 
     var next = start; 
     for(var i = 0; i<days; i++) { 
      next = next.AddDays(1); 
      yield return next; 
     } 
    } 
} 
4

在.NET 2.0 :)

static void Main(string[] args) 
    { 
     List<DateTime> dates = new List<DateTime>(); 
     dates.Add(new DateTime(2010, 01, 27)); 
     dates.Add(new DateTime(2010, 01, 30)); 
     dates.Add(new DateTime(2010, 01, 31)); 
     dates.Add(new DateTime(2010, 02, 01)); 


     DateTime startDate = new DateTime(2010, 01, 25); 
     DateTime endDate = new DateTime(2010, 02, 02); 

     List<DateTime> missingDates = new List<DateTime>(GetMissingDates(dates, startDate, endDate)); 

    } 

    private static IEnumerable<DateTime> GetMissingDates(IList<DateTime> dates, DateTime startDate, DateTime endDate) 
    { 
     TimeSpan _timeStamp = endDate - startDate; 
     DateTime _tempDateTime = startDate; 
     IList<DateTime> _dateTimeRange = new List<DateTime>(); 
     IList<DateTime> _missingDates = new List<DateTime>(); 

     for (int i = 0; i <= _timeStamp.Days; i++) 
     { 
      _dateTimeRange.Add(_tempDateTime); 
      _tempDateTime = _tempDateTime.AddDays(1); 
     } 

     foreach (DateTime dt in _dateTimeRange) 
     { 
      if (!dates.Contains(dt)) 
       yield return dt; 
     } 
    } 
+0

+1对于2.0 implmentation! – 2010-08-02 16:04:34