从对象中获取日期列表

Get List of dates from object

我读了几个线程,但不确定如何从一个范围中获取最早和最晚的日期。

数据示例(为简洁起见跳过了大多数列)

CustID StartDate   EndDate
1       01/01/2015  01/01/2015
2       03/01/2015  03/01/2015
3       03/01/2015  05/01/2015
4       03/01/2015  10/01/2015

UI 允许用户select 来自日历控件的日期。然后它应该得到上述范围内的所有日期,所以如果用户 selects

02/01/2015 - 没有 returned 因为没有 startDateEndDate 匹配此 date/range

如果他们 select 01/01/2015 那么我希望获得以下日期

01/01/2015
03/01/2015
04/01/2015
05/01/2015
.... to 10/01/2015

注意日期 02/01/2015 不包括在内。

如果用户 selects 03/01/2015 那么它将 return 所有日期直到 10/01/2015。

为了实现这个我写了代码

public List<DateTime> GetDates()
{

    IEnumerable<Customers> Dates = dc.Customers.Where(d => d.StartDate.Value >= DateTime.Now );

    DateTime FromDate = Dates.Where(f => f.StartDate.HasValue).Min(f => f.StartDate).Value;
    DateTime ToDate = Dates.Where(t => t.EndDate.HasValue).Max(f => f.EndDate).Value;

    IEnumerable<DateTime> AllDates = Enumerable.Range(0, int.MaxValue)
                 .Select(x => FromDate.Date.AddDays(x))
                 .TakeWhile(x => x <= ToDate.Date);

    return AllDates.ToList();
}

但它不是 return我预期的日期。使用此代码,如果我 select 01/01/2015,它 return 是所有日期?我哪里错了?

我的猜测是他正试图用其他客户已经 select 编辑过的日期填充日历控件,因此用户不能 select 它们,但他正试图减少项目的数量 returned 到一个较小的集合。当然,示例数据将是错误的,因为它已经有重叠的日期,所以...

第一关:

public List<DateTime> GetDates()
{

    IEnumerable<Customers> Dates = dc.Customers
      .Where(d => d.StartDate.Value >= DateTime.Now);

    var FromDate = Dates.Where(f => f.StartDate.HasValue)
      .Min(f => f.StartDate).Value;
    var ToDate = Dates.Where(t => t.EndDate.HasValue)
      .Max(f => f.EndDate).Value;


    IEnumerable<DateTime> AllDates = Enumerable.Range(0, int.MaxValue)
                 .Select(x => FromDate.Date.AddDays(x))
                 .TakeWhile(x => x <= ToDate.Date)
                 .Where(x=>dc.Customers.Any(c=>x>=c.StartDate && x<=c.EndDate));

    return AllDates.ToList();
}

这是一个更好的解决方案,但是 return 所有范围内的所有日期,通过在需要的地方添加 where 子句进一步减少。把它放在 .ToList 之前,如果你真的想排除所有没有开始日期 >= 你的 selection 的范围,或者如果你真的想包括它们,把它放在最后,但不是 return <您的 selection 的部分(更有可能)。

public List<DateTime> GetDates()
{
    return db.Customers
      .ToList()
      .Select(pair =>
             Enumerable.Range(0,(int)(pair.EndDate - pair.StartDate).TotalDays+1)
                       .Select(days => pair.StartDate.AddDays(days)))
      .SelectMany(x=>x)
      .Distinct();
}

奖金:

/* DateTime extension for ranges of dates */
public static class DateTimeExtensions
{
    public static IEnumerable<DateTime> EnumerableTo(this DateTime self, DateTime toDate)
    {
        for(var d=self;d<=toDate;d=d.Date.AddDays(1))
           yield return d;
    }
}
void Main()
{
    /* Your example data */
    var Customers=new [] {
      new { id=1,StartDate=new DateTime(2015,1,1),EndDate=new DateTime(2015,1,1)},
      new { id=2,StartDate=new DateTime(2015,1,3),EndDate=new DateTime(2015,1,3)},
      new { id=3,StartDate=new DateTime(2015,1,3),EndDate=new DateTime(2015,1,5)},
      new { id=4,StartDate=new DateTime(2015,1,3),EndDate=new DateTime(2015,1,10)},
    };

    /* The query */
    var results=Customers
       .Select(pair => pair.StartDate.EnumerableTo(pair.EndDate))
       .SelectMany(x=>x)
       .Distinct();

    results.Dump();
}

如果您想要的是所有客户的开始日期和结束日期的联合,其中开始日期大于用户选择的日期,那么为什么不像

return (from costumer in dc.Customers select costumer.startdate
           where costumer.startdate > UserSelectedDate)
   .Union
       (from costumer in dc.Customers select costumer.enddate
           where costumer.startdate > UserSelectedDate)
   .Distinct()

如果您想要的是用户选择的所有开始日期和结束日期都在该范围内,那么您会做

return (from costumer in dc.Customers select costumer.startdate
           where costumer.startdate <= UserSelectedDate and
                 UserSelectedDate <= costumer.enddate)
   .Union
       (from costumer in dc.Customers select costumer.enddate
           where costumer.startdate <= UserSelectedDate and
                 UserSelectedDate <= costumer.enddate)
   .Distinct()