【问题标题】:Determine if two time ranges overlap [duplicate]确定两个时间范围是否重叠[重复]
【发布时间】:2017-06-28 17:55:39
【问题描述】:

我正在使用算法编写调度程序。在算法的最后阶段,我需要查看时间表(创建的时间表),看看学生当时是否已经被分配到一个班级。

因此,我们有:

Current Class Start Time: (2017, 02, 09, 10, 00, 00)
Current Class Finish Time: (2017, 02, 09, 11, 00, 00)

此时我们将搜索时间表,看看学生 A 被分配到哪些其他班级:

例如,假设他们已经分配到同一日期:

Class 'Z' Start Time: (2017, 02, 09, 09, 00, 00)
Class 'Z' Finish Time: (2017, 02, 09, 12, 00, 00)

现在我想找到 Class 'Z' 的时间范围,并将其与 Current Class 的时间范围进行比较。

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime StartCurrent = new DateTime(2017, 02, 09, 10, 00, 00);
DateTime StartCurrent = new DateTime(2017, 02, 09, 11, 00, 00);

if (They do not clash)
{
   Assign
}
if (Clash)
{
   Select Another Student
}

谁能帮我解决我的“IF 语句”以及如何解决这个问题。

按照我的想法,有三种可能:

  1. 如果“当前班级”(开始和结束时间)介于“Z 级”(冲突 1)之间
  2. 如果“当前班级”的“开始时间”落在“Z 班”之间(冲突 2)
  3. 如果“当前班级”的“结束时间”落在“Z 班”之间(冲突 3)

谢谢

【问题讨论】:

  • “按照我的想法,有三种可能性”您是否尝试过实现它并看看会发生什么?你已经尝试过什么? stackoverflow.com/help/how-to-ask
  • 有超过 3 种可能性,因为类的长度不尽相同。所以你有四个变量:开始A,结束A,开始B,结束B。组合是:1)A在B开始之前开始和结束2)A在B之前开始并且在B之前结束3)A在B之前开始并且在之后结束B 4) A 在 B 之后开始,在 B 结束之前结束 5) A 在 B 之后开始,在 B 之后结束 6) A 在 B 结束之后开始
  • 否,因为我想知道是否有一个解决方案,我可以使用例如变量09:00:00 到 12:00:00 然后我可以使用 if 语句来查看开始时间结束时间或新变量(10:00:00 到 11:00:00)是否会落在 Z 类变量( 09:00:00 至 12:00:00)
  • @jdweng 你是对的,有第 4 种可能性:如果当前课程持续时间长于 Z 课程
  • Tim :我在回答中涵盖了所有 6 种可能的组合。你不能只看课程的长度。您的 if/else 语句必须涵盖所有 6 种情况。

标签: c# .net winforms datetime timespan


【解决方案1】:

这是最简单的方法:

public static bool HasOverlap(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
{
    return start1 < end2 && end1 > start2;
}

或者如果日期不一定是正确的开始/结束顺序:

public static bool HasOverlap(DateTime start1, DateTime end1, DateTime start2, DateTime end2)
{
    return Min(start1, end1) < Max(start2, end2) && Max(start1, end1) > Min(start2, end2);
}

public static DateTime Max(DateTime d1, DateTime d2)
{
    return d1 > d2 ? d1 : d2;
}

public static DateTime Min(DateTime d1, DateTime d2)
{
    return d2 > d1 ? d1: d2;
}

注意,如果一个类在 2 结束,而下一个从 2 开始,则不会有重叠。既然你在谈论课程,我假设这就是你想要的。

测试你的例子:

static void Main(string[] args)
{
    DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
    DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

    DateTime StartCurrent = new DateTime(2017, 02, 09, 10, 00, 00);
    DateTime EndCurrent = new DateTime(2017, 02, 09, 11, 00, 00);


    if(HasOverlap(startClassZ, endClassZ, StartCurrent, EndCurrent))
    {
        Console.WriteLine("clash");
    }
    else
    {
        Console.WriteLine("yay");
    }
    Console.Read();
}

我为你添加了一些快速测试:

public static void Test1()
{
    // Class A overlaps class B
    DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T10:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T11:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"1: {isCorrect}");
}

public static void Test2()
{
    // Class A "surrounds" class B
    DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T15:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T11:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"2: {isCorrect}");
}

public static void Test3()
{
    // Class B "surrounds" class A
    DateTime aStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T15:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"3: {isCorrect}");
}

public static void Test4()
{
    // Class A is before Class B
    DateTime aStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T11:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T12:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == false;
    Console.WriteLine($"4: {isCorrect}");
}

public static void Test5()
{
    // Class A is after Class B
    DateTime aStart = DateTime.Parse("2017-01-01T12:00:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T14:00:00");

    DateTime bStart = DateTime.Parse("2017-01-01T11:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T12:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == false;
    Console.WriteLine($"5: {isCorrect}");
}

public static void Test6()
{
    // Class B overlaps class A
    DateTime bStart = DateTime.Parse("2017-01-01T09:00:00");
    DateTime bEnd = DateTime.Parse("2017-01-01T10:00:00");

    DateTime aStart = DateTime.Parse("2017-01-01T09:30:00");
    DateTime aEnd = DateTime.Parse("2017-01-01T11:00:00");

    bool isCorrect = HasOverlap(aStart, aEnd, bStart, bEnd) == true;
    Console.WriteLine($"6: {isCorrect}");
}

static void Main()
{
    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    Test6();
    Console.Read();
}

【讨论】:

  • 但是为什么会有 3 组代码呢?前两套我都懂,那第三套呢?
  • @TimJones 什么?第一个是您需要的代码,另一个是您的示例,第三个是一组逻辑测试用例,它们都应该返回 true 以证明它有效。尤其是当其他回答的人似乎认为它不起作用时,证明它是明智的。
  • 投反对票的任何理由,神秘的投反对票。请提供该功能不起作用的测试用例。
  • 不!它实际上正在工作。干得好伙伴...只有一个问题(但是用户不能在完成日期之前输入开始日期)但是如果我们有 15:00:00 到 13:00:00 它将给出错误的答案。因此,它将允许分配学生。顺便说一句,我没有给你投反对票
  • @TimJones 我添加了另一个示例,其中包含几种选择最大/最小日期值的方法,以便检查不关心开始/结束的顺序。
【解决方案2】:

您需要仔细检查: 在这种情况下使用当前的 classZ

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime startCurrent = new DateTime(2017, 02, 10, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 11, 00, 00);

当前使用 Z 类

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime startCurrent = new DateTime(2017, 02, 08, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 13, 00, 00);

完整代码在这里:

DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00);
DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00);

DateTime startCurrent = new DateTime(2017, 02, 08, 10, 00, 00);
DateTime endCurrent = new DateTime(2017, 02, 09, 13, 00, 00);


bool ClashCurrentStart = startClassZ < startCurrent && startCurrent < endClassZ;
bool ClashCurrentEnd = startClassZ < endCurrent && endCurrent < endClassZ;
//bool ClashCurrentBetween = ClashCurrentStart && ClashCurrentEnd;

bool ClashClassZStart = startCurrent < startClassZ && startClassZ < endCurrent;
bool ClashClassZEnd = startCurrent < endClassZ && endClassZ < endCurrent;
//bool ClashClassZBetween = ClashClassZStart && ClashClassZEnd;


bool Clash = ClashCurrentStart || ClashCurrentEnd || ClashClassZStart || ClashClassZEnd;

if (!Clash)
{
    //Assign
}
else // Clash
{
    //Select Another Student
}

【讨论】:

  • 这太复杂了。
  • 这适用于:DateTime startClassZ = new DateTime(2017, 02, 09, 09, 00, 00); DateTime endClassZ = new DateTime(2017, 02, 09, 12, 00, 00); DateTime StartCurrent = new DateTime(2017, 02, 09, 08, 00, 00); DateTime EndCurrent = new DateTime(2017, 02, 09, 13, 00, 00);但你的代码不起作用
  • 我的代码表明这些时间会导致重叠。我的大脑也暗示这些时间是重叠的。也许你应该在你说它不起作用之前尝试我的代码?
  • 对不起@john,你说得对!您的“HasOverlap”功能运行良好!
  • 感谢您的实际检查:)
【解决方案3】:

您提供了三种可能性:

A) 整个currentClasszClass

B) currentClass 的开头在 zClass

C) currentClass 的结尾在 zClass

我想指出,A) 与 B) 和 C) 组合的含义相同,因此不需要特别注意。此外,如果您尝试在脑海中(或在纸上)画出最简单的课程持续时间草图,那么这些条件会很自然地弹出:

clash = (endOfCurrentClass &gt; startOfZClass) || (startOfCurrentClass &lt; endOfZClass)

剩下的就是考虑等效性(例如endOfCurrentClass == startOfZClass),但这取决于其他约束(上课时间是否包含课程之间的停顿?他们在同一个房间吗?...)。然而这是另一个问题。

【讨论】:

    猜你喜欢
    • 2016-02-14
    • 2012-11-03
    • 2011-06-10
    • 1970-01-01
    • 1970-01-01
    • 2016-06-30
    • 2017-06-08
    • 2015-10-15
    • 1970-01-01
    相关资源
    最近更新 更多