本文翻译自:Algorithm to detect overlapping periods [duplicate]
This question already has an answer here: 这个问题在这里已有答案:
- Determine Whether Two Date Ranges Overlap 34 answers 确定两个日期范围是否重叠 34答案
I've to detect if two time periods are overlapping. 我要检测两个时间段是否重叠。
Every period has a start date and an end date. 每个期间都有开始日期和结束日期。
I need to detect if my first time period (A) is overlapping with another one(B/C). 我需要检测我的第一个时间段(A)是否与另一个时间段(B / C)重叠。
In my case, if the start of B is equal to the end of A, they are not overlapping(the inverse too) 在我的情况下,如果B的起点等于A的结尾,则它们不重叠(反之亦然)
I found the following cases: 我发现了以下情况:
So actually I'm doing this like this: 所以实际上我这样做是这样的:
tStartA < tStartB && tStartB < tEndA //For case 1
OR
tStartA < tEndB && tEndB <= tEndA //For case 2
OR
tStartB < tStartA && tEndB > tEndA //For case 3
(The case 4 is taken in the account either in case 1 or in case 2) (案例4在案例1或案例2中被记入帐户)
It works , but it seems not very efficient. 它有效 ,但似乎效率不高。
So, first is there an existing class in c# that can modelize this(a time period), something like a timespan, but with a fixed start date. 所以,首先在c#中有一个现有的类可以对此进行建模(一个时间段),类似于时间跨度,但具有固定的开始日期。
Secondly: Is there already ac# code(like in the DateTime
class) which can handle this? 第二:是否已经有ac#代码(比如在DateTime
类中)可以处理这个问题?
Third: if no, what would be your approach to make this comparison the most fast? 第三:如果不是,那么你最快速地进行这种比较的方法是什么?
#1楼
参考:https://stackoom.com/question/uhae/检测重叠周期的算法-重复
#2楼
Simple check to see if two time periods overlap: 只需检查两个时间段是否重叠:
bool overlap = a.start < b.end && b.start < a.end;
or in your code: 或者在你的代码中:
bool overlap = tStartA < tEndB && tStartB < tEndA;
(Use <=
instead of <
if you change your mind about wanting to say that two periods that just touch each other overlap.) (如果你改变主意想要说两个相互接触的时期重叠,那就用<=
代替<
。
#3楼
There is a wonderful library with good reviews on CodeProject: http://www.codeproject.com/Articles/168662/Time-Period-Library-for-NET 有一个很棒的图书馆,对CodeProject有很好的评价: http : //www.codeproject.com/Articles/168662/Time-Period-Library-for-NET
That library does a lot of work concerning overlap, intersecting them, etc. It's too big to copy/paste all of it, but I'll see which specific parts which can be useful to you. 那个库在重叠,交叉它们等方面做了很多工作。复制/粘贴它们太大了,但是我会看到哪些特定的部分对你有用。
#4楼
How about a custom interval-tree structure? 自定义区间树结构怎么样? You'll have to tweak it a little bit to define what it means for two intervals to "overlap" in your domain. 您需要稍微调整一下,以定义在您的域中“重叠”两个间隔的含义。
This question might help you find an off-the-shelf interval-tree implementation in C#. 这个问题可能有助于您在C#中找到现成的区间树实现。
#5楼
You can create a reusable Range pattern class : 您可以创建可重用的Range模式类:
public class Range<T> where T : IComparable
{
readonly T min;
readonly T max;
public Range(T min, T max)
{
this.min = min;
this.max = max;
}
public bool IsOverlapped(Range<T> other)
{
return Min.CompareTo(other.Max) < 0 && other.Min.CompareTo(Max) < 0;
}
public T Min { get { return min; } }
public T Max { get { return max; } }
}
You can add all methods you need to merge ranges, get intersections and so on... 您可以添加合并范围,交叉点等所需的所有方法......
#6楼
I don't believe that the framework itself has this class. 我不相信框架本身就有这个类。 Maybe a third-party library... 也许是第三方图书馆......
But why not create a Period value-object class to handle this complexity? 但是为什么不创建一个Period值对象类来处理这种复杂性呢? That way you can ensure other constraints, like validating start vs end datetimes. 这样您就可以确保其他约束,例如验证开始日期和结束日期时间。 Something like: 就像是:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Whatever.Domain.Timing {
public class Period {
public DateTime StartDateTime {get; private set;}
public DateTime EndDateTime {get; private set;}
public Period(DateTime StartDateTime, DateTime EndDateTime) {
if (StartDateTime > EndDateTime)
throw new InvalidPeriodException("End DateTime Must Be Greater Than Start DateTime!");
this.StartDateTime = StartDateTime;
this.EndDateTime = EndDateTime;
}
public bool Overlaps(Period anotherPeriod){
return (this.StartDateTime < anotherPeriod.EndDateTime && anotherPeriod.StartDateTime < this.EndDateTime)
}
public TimeSpan GetDuration(){
return EndDateTime - StartDateTime;
}
}
public class InvalidPeriodException : Exception {
public InvalidPeriodException(string Message) : base(Message) { }
}
}
That way you will be able to individually compare each period... 这样你就可以单独比较每个时期......