我正在尝试在DateTimes集合的两个DateTime变量之间找到缺少的日期。
例如。
Collection
2010-01-01
2010-01-02
2010-01-03
2010-01-05
DateRange
2010-01-01 -> 2010-01-06
会给我一个List<DateTime>
2010-01-04
2010-01-06
我可以想到一些是实现这个但没有什么干净和简单的
有什么想法吗?
答案 0 :(得分:17)
我可以想到很多方法来实现这一点,例如:
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);
但也许这不是一个高性能解决方案: - )
答案 1 :(得分: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;
}
}
答案 2 :(得分:3)
具体取决于您要查找的内容以及数据集的大小。一种简单的方法是将日期加载到集合中,然后使用简单的循环。我将在一秒钟内添加一个代码示例。
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”列表将显示您的结果
答案 3 :(得分: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() );
如果您正在考虑解决这个问题,那么除非您还有最短和最长日期之间的所有日期列表,否则我认为不可能。在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() );
答案 4 :(得分: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;
}
}
}