【问题标题】:Business Hours of Operation in SQL/C#SQL/C#中的营业时间
【发布时间】:2010-06-08 09:20:45
【问题描述】:

出于某种原因,我在这个问题上放了一个大脑袋。 我有一张写有“营业时间”的表格。 该表有: - 日(星期一 = 1,星期日 = 7) - 开始时间 - 结束时间

我正在尝试找出如何编写最简洁的代码(使用 Linq to SQL)来检查时间是否在提交新时间时重叠并相应地修改所有记录。 例如,如果数据库已经有这些记录: - 开始 = 上午 8 点,结束 = 中午 - 开始 = 下午 2 点,结束 = 下午 5 点

有人补充说: - 开始 = 中午,结束 = 下午 6 点

我希望代码弄清楚如何组合这 3 条记录并留下一条记录。但是我还需要能够仅在必要时进行组合,因此如果有人要插入它: - 开始 = 中午,结束 = 下午 1 点

然后我会得到 2 条记录(第一条将被修改)。

就像我说的......我似乎无法解决这个问题。 帮忙?

【问题讨论】:

标签: c# sql linq-to-sql


【解决方案1】:

我建议您对时间间隔表示稍作更改,以使用 Length 属性而不是 EndTime 属性。

class TimeInterval
{
    public int Day { set; get; }
    public DateTime StartTime { set; get; }
    public int Length { set; get; }
}

由于我们对查找重叠间隔感兴趣,所以接下来的方法会很方便,我会将它们放在 TimeInterval 类中。

public int StartMinuteInWeek()
{
    return Day * 24 * 60 + StartTime.Hour * 60 + StartTime.Minute;
}

public int EndMinuteInWeek()
{
    return StartMinuteInWeek() + Length;
}

然后您只需要找到与您的新时间间隔重叠的任何 TimeInterval。您必须注意,新间隔可以扩展任何现有的间隔,甚至可以连接两个单独的间隔,或者只是包含在已定义的间隔中。

要获取在间隔开始时重叠的记录,请使用以下查询:

var startOverlap = (from rec in intervals
    where rec.StartMinuteInWeek() <= timeInterval.StartMinuteInWeek() && rec.EndMinuteInWeek() >= timeInterval.StartMinuteInWeek()
    select rec).FirstOrDefault();

timeInterval 是您尝试添加的新间隔。

对于末端重叠,请使用以下之一:

var endOverlap = (from rec in intervals
    where rec.StartMinuteInWeek() <= timeInterval.EndMinuteInWeek() && rec.EndMinuteInWeek() >= timeInterval.EndMinuteInWeek()
    select rec).FirstOrDefault();

如果 startOverlap 为 null,则间隔开始时没有重叠。 endOverlap 也是如此。 如果 startOverlap == endOverlap,则新区间完全包含在现有区间内。

我已将 StartTime 定义为 DateTime 类型,虽然我只对时间部分感兴趣,但如果您想要两个名为 Hour 和 Minute 的字段,或者可能只有一个表示开始分钟的字段,您可以更改它间隔的星期。

编辑

正如我在评论中提到的,我已经意识到一个新的时间间隔可以与几个已经定义的时间间隔重叠。例如,如果通常操作从 8:00 到 20:00 并在午餐时间停止,现在定义了一个新的时间间隔,该时间间隔贯穿整个一周 24x7,那么新的时间间隔将包含 14 个间隔。

一个安全的方法是先检测所有重叠的区间,然后调整新的区间以确保它完全包含任何重叠的区间,最后删除所有的重叠。

为了确定新间隔是否与旧间隔重叠,我将在 TimeInterval 类中定义这个方便的方法。

public bool IsInsideInterval(int minuteInWeek)
{
    return minuteInWeek >= StartMinuteInWeek() &&
        minuteInWeek <= EndMinuteInWeek();
}

现在我正在找出开始分钟或结束分钟的所有间隔都在新间隔内。

var overlaps = (from rec in intervals where
    newInterval.IsInsideInterval(rec.StartMinuteInWeek()) ||
    newInterval.IsInsideInterval(rec.EndMinuteInWeek())
    select rec).ToList();

现在您必须确保新的间隔限制正常。

foreach (TimeInterval rec in overlaps)
{
    if (rec.StartMinuteInWeek() < newInterval.StartMinuteInWeek())
    {
        newInterval.Day = rec.Day;
        newInterval.StartTime = rec.StartTime;
    }
    if (rec.EndMinuteInWeek() > newInterval.EndMinuteInWeek())
    {
        // You have to calc the Length being careful to not count twice the minutes that overlaps.
        newInterval.Length = newInterval.Length + rec.Length - (newInterval.EndMinuteInWeek() - rec.StartMinuteInWeek());
    }
}

最后你可以删除overlaps中的所有区间,然后插入newInterval

【讨论】:

  • 我刚刚意识到这个问题比我最初想象的要复杂一些。一个新的时间间隔可以与几个已经定义的间隔重叠。我正在更新!
猜你喜欢
  • 2011-02-12
  • 2011-11-08
  • 2015-03-07
  • 1970-01-01
  • 1970-01-01
  • 2018-01-21
  • 2015-04-11
  • 1970-01-01
  • 2014-05-31
相关资源
最近更新 更多