使用LINQ检查时间表重叠

4

我有一个如下表格:

SL  Classroom  Weekday  StartTime  EndTime
--  ---------  -------  ---------  --------  
1   ADMN-100   Friday   01:00:00   02:00:00
2   ADMN-100   Friday   02:00:00   03:00:00
3   ADMN-100   Monday   01:00:00   02:00:00
4   LAB-501    Monday   01:00:00   02:00:00

使用LINQ,我如何检查时间重叠是否发生?

我尝试了以下代码但失败了:

bool check = true;
check = db.Classrooms.Any(x => x.Classroom.Equals(roomNo)
                                   && x.Weekday.Equals(weekDay)
                                   && x.StartTime < startsAt
                                   && x.EndTime > startsAt);

你在这里缺少一些细节,但是你的符号是否反了?你应该检查开始时间是否早于 startsAt。 - Casey
我认为应该是 startsAt > x.StartTime && x.EndTime > startsAt - Arturo Menchaca
检查重叠的方法是 start1 < end2 && start2 < end1 - juharr
Casey、Arturo Menchaca和juharr,你们说得对。我已经修改了问题以及我的代码。但是还没有解决。 - Tareq
@JohnCarpenter,时间属性是TimeSpan类型,在数据注释中使用[DataType(DataType.Time)]。因此,除了时间之外没有其他组件。 - Tareq
显示剩余3条评论
5个回答

3
你的代码几乎正确,但需要将 x.StartTime < startsAt 改为 x.StartTime < endsAt。为了完整起见,下面是 Schedule 类的内容。
class Schedule
{
    public string Classroom { get; set; }
    public string Weekday { get; set; }
    public TimeSpan StartTime { get; set; }
    public TimeSpan EndTime { get; set; }

    public bool OverlapsWith(Schedule schedule)
    {
        return schedule.StartTime < EndTime && 
               schedule.EndTime > StartTime && 
               schedule.Weekday == Weekday && 
               schedule.Classroom == Classroom;
    }
}

快速提示-使用TimeSpan以便DateTime对象在月份、年份或日期出现错误时不会破坏您的逻辑。 你真正想要的是一天中的时间,而TimeSpan提供了“小时”,“分钟”和“秒”,这正是你想要的。比较将与TimeSpan对象一起工作。不过我不确定这在EF中是否可行。
如果您需要将字符串转换为TimeSpan,请尝试TimeSpan.Parse。它应该适用于您在问题中提出的格式。 OverlapsWith方法可能不会在Schedule内部,但它只是为了向您展示您的代码基本相同。

1
“自一天开始以来经过的时间”与“当天时间”是相同的概念。我所知道的最接近这种方式的解释就是按照TimeSpan执行。请参考问题链接 中关于该主题的其他 SO 帖子。 - Frank Bryce
是的,我的类属性声明就像你展示的那样。 - Tareq
@Tareq,你还有问题吗?哪个情况没有起作用?在你的四个时间表的例子中,我没有看到任何重叠。你还测试了更多数据吗? - Frank Bryce
@JohnCarpenter,它部分地起作用。比如,考虑到教室=ADMN-100,星期五,如果我输入1:30,那么它可以正常工作并显示时间重叠,这对于SL-1是正确的。但是,如果考虑相同的教室和星期几,如果我输入2:30,则应该说时间重叠,因为SL-2有日程安排,但它不起作用。 - Tareq
如果在同一时间使用不同的教室,则不会发生重叠。只有在同一天的同一时间使用相同的教室才会发生重叠,对吗?看起来您希望在同时使用两个不同的教室时出现重叠。如果您想要这样,请从查询中删除 x.Classroom.Equals(roomNo) - Frank Bryce
显示剩余2条评论

0

为什么不尝试使用 Datetime.Compare() 方法呢?像这样:

.Any(
Datetime.Compare(x.StartTime, startsAt)>0 
&&
Datetime.Compare(x.EndTime, startsAt)<0
)

1
我认为 DateTime.Compare 在 EF 中无法转换为 SQL 。但它与仅使用运算符并没有什么不同。 - juharr

0
其他答案没有涵盖所有可能的重叠情况。这就是你想要的。
check = classes.Any(x=>x.Classroom.Equals(roonNo)
                       && x.Weekday.Equals(weekDay)
                       && x.StartTime <= endsAt
                       && x.EndTime >= startsAt);

如果您没有“endsAt”时间,您可以在两个位置都使用“startsAt”,结果是相同的。尽管这会降级为Matt Rowlands的答案。 - Callback Kid

0

选择具有匹配结果的元素

      var v=  c.ones.Select(x=>x).Where(x =>  x.weekday.Equals("mon")
                               && x.starttime == TimeSpan.Parse("08:00")
                               && x.endtime == TimeSpan.Parse("09:00"));

查找是否存在重叠

     IQueryable<bool> v=  c.ones.Select(x =>  x.weekday.Equals("mon")
                               && x.starttime == TimeSpan.Parse("08:00")
                               && x.endtime == TimeSpan.Parse("09:00"));

0

已解决

我想做这样的事情,因为我必须遍历每一行来查找组合。

foreach (var val in DataSource)
        {
            if (roomNo.Equals(val.Classroom))
            {
                if (weekDay.Equals(val.ClassRoomWeekDay))
                {
                    if (startsAt>= val.StartTime && startsAt< val.EndTime )
                    {
                        check = false;
                    }

                }
            }

        }

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