使用Linq检查日期是否在范围内

4

我目前正在处理一个需要检查两个日期之间可用性的项目。我的当前方法未返回预期结果。例如,假设我有以下预订:

  • 2015年4月13日至2015年4月18日
  • 2015年4月15日至2015年4月20日
  • 2015年4月10日至2015年4月16日

我希望查看所有在2015年4月15日至2015年4月16日期间的预订。从视觉上看,可能如下所示:

              15    16
      X________|_____|______X
               |X____|_____________X
X______________|____X|
               |     | 

为了获取在这些日期之间的所有预订,我正在使用以下方法:
public List<ReservationClientModel> GetReservationsByDateRange(int id, DateTime checkin, DateTime checkout)
    {
        var reservation = _repository.FindAllBy(x => 
            (x.StartDate >= checkin && x.EndDate <= checkout) ||
            (x.StartDate >= checkin && x.StartDate <= checkout) ||
            (x.EndDate >= checkin && x.EndDate <= checkout)),
            y => y.RoomTypeNav)
            .ToList();

        return Mapper.Map<List<ReservationClientModel>>(reservation);
    }

这是使用哪个:

public IEnumerable<TEntity> FindAllBy(Expression<Func<TEntity, bool>> predicate, params Expression<Func<TEntity, object>>[] includes)
    {
        var set = _dbSet.AsQueryable();
        set = includes.Aggregate(set, (current, include) => current.Include(include));
        return set.Where(predicate);
    }

这将仅返回最后两个预订,我认为这是因为它在日期上检查了><,而不是检查它是否在范围内。我知道可以使用SQL BETWEEN运算符,但我想知道是否有任何方法可以使用Linq表达式或从C#中执行此操作?理想情况下,我希望将其作为EF查询的一部分执行,而不是返回所有预订,然后对此列表执行操作。感谢您的帮助。

1
你的开始日期和结束日期的运算符不需要交换吗?x.StartDate >= checkin 表示他们在 x.StartDate 之前签到(x.StartDate 大于或等于 checkin),然后对于 enddate,x.EndDate <= checkout 表示 checkout 大于或等于 x.EndDate。这是你想要的结果吗? - CalebB
@CalebB,是的,我认为那是正确的。问题出在我的思考方式上。我试图确定开始和结束日期是否在我的范围内,或者开始日期或结束日期单独落在我的范围内。现在想想,这种方法有点奇怪! - moikey
1个回答

11

如果满足以下规则,则两个范围重叠:

(StartDate1 <= EndDate2) and (EndDate1 >= StartDate2)

通过将这个规则应用到您的代码中,您将得到:

var reservation = _repository
    .FindAllBy(x => x.StartDate <= checkout && x.EndDate >= checkin,  
               y => y.RoomTypeNav)
    .ToList();

简单明了。现在看到写下来就很容易,哈哈。谢谢Kaspars! - moikey

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接