我正在尝试为两个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>
的是实现这个的,但没有干净和简单
任何想法?
我正在尝试为两个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>
的是实现这个的,但没有干净和简单
任何想法?
我想了很多,实施这个办法,例如:
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);
但也许这并不是一个高性能的解决方案:-)
具体取决于您要查找的内容以及数据集的大小。一个简单的方法是将日期加载到一个集合中,然后使用一个简单的循环。我会在第二秒添加一个代码示例。
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”名单将有你的结果
是否使用。载有(..)有没有好的办法?将整个数组与整个迭代中的一个项匹配。我没有进行基准测试,但是我会去找一个Where和Count命中<1的地方。 – Independent 2011-09-16 15:26:50
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());
懒惰评估辅助方法,有助于生成日期与比较的列表。可能想要为大型集合评估此方法。
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;
}
}
}
在.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;
}
}
+1对于2.0 implmentation! – 2010-08-02 16:04:34
这与我的想法类似,除了使用for循环来建立我的范围。我只是不喜欢每次建立一个日子清单的想法,因为我必须做很多安静的事情。 – 2010-08-02 14:05:25
+1很好的使用范围。 – Thomas 2010-08-02 14:05:26
是的,巧妙的使用范围;) – 2010-08-02 14:07:59