MomentInterval a = MomentInterval.between(Instant.now(), Instant.now().plusSeconds(2));
MomentInterval b = a.collapse(); // make b an empty interval out of a
System.out.println(a); // [2017-04-10T05:28:11,909000000Z/2017-04-10T05:28:13,909000000Z)
System.out.println(b); // [2017-04-10T05:28:11,909000000Z/2017-04-10T05:28:11,909000000Z)
A = [StartA, EndA]
B = [StartB, EndB]
[---- DateRange A ------] (True if StartA > EndB)
[--- Date Range B -----]
[---- DateRange A -----] (True if EndA < StartB)
[--- Date Range B ----]
重叠敌我识别码: (StartA <= EndB) and (EndA >= StartB) 情况2:a、b为开放区间
A = (StartA, EndA)
B = (StartB, EndB)
(---- DateRange A ------) (True if StartA >= EndB)
(--- Date Range B -----)
(---- DateRange A -----) (True if EndA <= StartB)
(--- Date Range B ----)
重叠敌我识别码: (StartA < EndB) and (EndA > StartB) 案例3:a,b右开
A = [StartA, EndA)
B = [StartB, EndB)
[---- DateRange A ------) (True if StartA >= EndB)
[--- Date Range B -----)
[---- DateRange A -----) (True if EndA <= StartB)
[--- Date Range B ----)
重叠条件: (StartA < EndB) and (EndA > StartB) 情况4:a、b左开
A = (StartA, EndA]
B = (StartB, EndB]
(---- DateRange A ------] (True if StartA >= EndB)
(--- Date Range B -----]
(---- DateRange A -----] (True if EndA <= StartB)
(--- Date Range B ----]
重叠条件: (StartA < EndB) and (EndA > StartB) 案例5:a右开,b右关
A = [StartA, EndA)
B = [StartB, EndB]
[---- DateRange A ------) (True if StartA > EndB)
[--- Date Range B -----]
[---- DateRange A -----) (True if EndA <= StartB)
[--- Date Range B ----]
对于时间关系(或任何其他区间关系)的推理,请考虑allen的区间代数。它描述了两个间隔之间可能存在的13种关系。你可以找到其他的参考资料-“艾伦间隔”似乎是一个有效的搜索词。您还可以在snodgrass开发的面向时间的sql应用程序(pdf可在线访问url)以及date、darwen和lorentzos temporal data and the relational model(2002年)或time and relational theory:temporal databases in the relational model and sql(2014年;实际上是td&rm的第二版)。 简短的回答是:给定两个日期间隔 A 以及 B 带组件 .start 以及 .end 以及约束条件 .start <= .end ,则两个间隔重叠,如果:
/**
* Compares to comparable objects to find out whether they overlap.
* It is assumed that the interval is in the format [from,to) (read: from is inclusive, to is exclusive).
* A null value is interpreted as infinity
*/
function intervalsOverlap(from1, to1, from2, to2) {
return (to2 === null || from1 < to2) && (to1 === null || to1 > from2);
}
SELECT DISTINCT T1.EmpID
FROM Table1 T1
INNER JOIN Table2 T2 ON T1.EmpID = T2.EmpID
AND T1.JobID <> T2.JobID
AND (
(T1.DateFrom >= T2.DateFrom AND T1.dateFrom <= T2.DateTo)
OR (T1.DateTo >= T2.DateFrom AND T1.DateTo <= T2.DateTo)
OR (T1.DateFrom < T2.DateFrom AND T1.DateTo IS NULL)
)
AND NOT (T1.DateFrom = T2.DateFrom)
var isOverlapping = ((A == null || D == null || A <= D)
&& (C == null || B == null || C <= B)
&& (A == null || B == null || A <= B)
&& (C == null || D == null || C <= D));
CREATE FUNCTION IsOverlapDates
(
@startDate1 as datetime,
@endDate1 as datetime,
@startDate2 as datetime,
@endDate2 as datetime
)
RETURNS int
AS
BEGIN
DECLARE @Overlap as int
SET @Overlap = (SELECT CASE WHEN (
(@startDate1 BETWEEN @startDate2 AND @endDate2) -- caters for inner and end date outer
OR
(@endDate1 BETWEEN @startDate2 AND @endDate2) -- caters for inner and start date outer
OR
(@startDate2 BETWEEN @startDate1 AND @endDate1) -- only one needed for outer range where dates are inside.
) THEN 1 ELSE 0 END
)
RETURN @Overlap
END
GO
--Execution of the above code
DECLARE @startDate1 as datetime
DECLARE @endDate1 as datetime
DECLARE @startDate2 as datetime
DECLARE @endDate2 as datetime
DECLARE @Overlap as int
SET @startDate1 = '2014-06-01 01:00:00'
SET @endDate1 = '2014-06-01 02:00:00'
SET @startDate2 = '2014-06-01 01:00:00'
SET @endDate2 = '2014-06-01 01:30:00'
SET @Overlap = [dbo].[IsOverlapDates] (@startDate1, @endDate1, @startDate2, @endDate2)
SELECT Overlap = @Overlap
20条答案
按热度按时间gpnt7bae1#
记住解决方法的简单方法是
min(ends)>max(starts)
ut6juiuv2#
最简单的
最简单的方法是使用精心设计的专用库进行日期时间工作。
java.time和额外的310
行业中最好的就是
java.time
内置于Java8及更高版本的框架。再加上一个额外的项目,它用额外的类来补充java.time,特别是Interval
我们需要上课。至于
language-agnostic
在这个问题上,两个项目的源代码都可以在其他语言中使用(注意他们的许可证)。间隔
这个
org.threeten.extra.Interval
上课很方便,但需要约会时间(java.time.Instant
对象)而不是仅日期值。因此,我们继续使用utc中一天的第一个时刻来表示日期。创建
Interval
代表那一段时间。我们还可以定义
Interval
开始时刻加上Duration
.与重叠测试相比很容易。
你可以比较
Interval
对抗另一个Interval
或者Instant
:abuts
containsencloses
equalsisAfter
isBeforeoverlaps
所有这些都使用Half-Open
一种定义时间跨度的方法,其中开始是包含的,结束是独占的。ovfsdjhp3#
@bretana给出的数学解很好,但忽略了两个具体细节:
闭间期或半开间期
空间隔
关于区间边界的开闭状态,@bretana的解对闭区间有效
(starta<=endb)和(enda>=startb)
可重写为半开间隔:
(starta<endb)和(enda>startb)
这种校正是必要的,因为开放区间边界不属于定义上的区间值范围。
关于空间隔,这里上面的关系并不成立。根据定义,不包含任何有效值的空间隔必须作为特殊情况处理。我用java时间库time4j通过以下示例演示:
前面的方括号“[”表示开始闭合,最后一个括号“)”表示结束开放。
如上图所示,空中提琴
ccgok5k54#
我会的
哪里
IsBetween
有点像pu3pd22g5#
这是对charles bretana优秀答案的扩展。
然而,答案并没有区分开、闭和半开(或半闭)区间。
情况1:a、b为闭合区间
重叠敌我识别码:
(StartA <= EndB) and (EndA >= StartB)
情况2:a、b为开放区间重叠敌我识别码:
(StartA < EndB) and (EndA > StartB)
案例3:a,b右开重叠条件:
(StartA < EndB) and (EndA > StartB)
情况4:a、b左开重叠条件:
(StartA < EndB) and (EndA > StartB)
案例5:a右开,b右关重叠条件:
(StartA <= EndB) and (EndA > StartB)
等。。。最后给出了两个区间重叠的一般条件
(开始<?endb)和(enda>?星(TB)
哪里?当比较两个包含的端点时,将严格不等式转化为非严格不等式。
j8yoct9x6#
我认为,如果出现以下情况,就可以说这两个范围是重叠的:
bwitn5fc7#
对于时间关系(或任何其他区间关系)的推理,请考虑allen的区间代数。它描述了两个间隔之间可能存在的13种关系。你可以找到其他的参考资料-“艾伦间隔”似乎是一个有效的搜索词。您还可以在snodgrass开发的面向时间的sql应用程序(pdf可在线访问url)以及date、darwen和lorentzos temporal data and the relational model(2002年)或time and relational theory:temporal databases in the relational model and sql(2014年;实际上是td&rm的第二版)。
简短的回答是:给定两个日期间隔
A
以及B
带组件.start
以及.end
以及约束条件.start <= .end
,则两个间隔重叠,如果:您可以调整
>=
与>
以及<=
与<
以满足您对重叠程度的要求。埃里克评论:
如果你把有趣的事情算进去,你只能得到13分。。。我可以得到“15个可能的关系,两个间隔可以有”当我疯了。通过合理的计算,我只得到六个,如果你不在乎a或b是第一个,我只得到三个(不相交,部分相交,一个完全在另一个内)。15是这样的:[before:before,开始,在内,结束,在后][start:start,内,尾,后][within:within,结束,之后][end:end,之后][after:after].
我想你不能数这两个条目before:before'和'after:after'. 我可以看到7个条目,如果你把它们的一些关系与它们的倒数相等(见维基百科网址中的图表;它有7个条目,其中6个具有不同的逆,而equals没有不同的逆)。三个是否合理取决于你的要求。
ntjbwcob8#
下面是另一个使用javascript的解决方案。我的解决方案的特点:
将空值处理为无穷大
假设下限是包含的,上限是独占的。
有很多测试
测试是基于整数的,但是由于javascript中的日期对象是可比较的,所以您也可以输入两个日期对象。或者你可以加上毫秒时间戳。
代码:
测试:
与karma&jasmine&phantomjs一起运行时的结果:
phantomjs 1.9.8(linux):成功执行20次(0.003秒/0.004秒)
9avjhtql9#
所有的解决方案,检查了大量的条件的基础上,范围是相互关系,可以大大简化,只要确保一个特定的范围开始更早!如果需要的话,可以通过预先交换范围来确保第一个范围更早开始(或者同时开始)。
然后,如果另一个范围开始小于或等于第一个范围结束(如果范围包含开始时间和结束时间)或小于(如果范围包含开始时间和结束时间),则可以检测重叠。
假设两端都包含,只有四种可能性,其中一种是不重叠的:
范围2的端点没有进入它。所以,在伪代码中:
这可以进一步简化为:
如果范围在开始时是包含的,在结束时是独占的,则只需替换
>
与>=
在第二个if
语句(对于第一个代码段:在第二个代码段中,您将使用<
而不是<=
):你极大地限制了你必须做的检查的数量,因为通过确保范围1永远不会在范围2之后开始,你提前消除了一半的问题空间。
x33g5p2x10#
答案对我来说太简单了,所以我创建了一个更通用的动态sql语句来检查一个人是否有任何重叠的日期。
4zcjmb1e11#
下面是实现这一魔力的代码:
哪里。。
a->1开始
b->1结束
c->2启动
d->2结束
证据?查看这个测试控制台代码。
57hvy0tb12#
这是我使用moment.js的javascript解决方案:
vql8enpb13#
如果还应计算重叠本身,则可以使用以下公式:
5f0d552i14#
在microsoft sql server中-sql函数
xyhw6mcr15#
(starta<=endb)和(enda>=startb)
证明:
让conditiona表示daterange a完全在daterange b之后
(如果
StartA > EndB
)让conditionb表示daterange a完全在daterange b之前
(如果
EndA < StartB
)如果a和b都不为真,则存在重叠-
(如果一个范围既不完全在另一个范围之后,
也不是完全在另一个之前,那么它们必须重叠。)
德摩根的一条定律说:
Not (A Or B)
<=>Not A And Not B
也就是说:(StartA <= EndB) and (EndA >= StartB)
注意:这包括边完全重叠的情况。如果你想排除这一点,更改
>=
操作员到>
,和<=
至<
注2。感谢@baodad,看看这个博客,实际重叠最少的是:{
endA-startA
,endA - startB
,endB-startA
,endB - startB
}(StartA <= EndB) and (EndA >= StartB)
(StartA <= EndB) and (StartB <= EndA)
注3。感谢@tomosius,一个简短的版本写道:DateRangesOverlap = max(start1, start2) < min(end1, end2)
这实际上是一个较长实现的语法快捷方式,包括额外的检查,以验证开始日期是否在结束日期或之前。从上面得出:如果开始和结束日期可能不正常,即,如果有可能
startA > endA
或者startB > endB
,那么您还必须检查它们是否有序,这意味着您必须添加两个额外的有效性规则:(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB)
或:(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB)
或者,(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB))
或:(Max(StartA, StartB) <= Min(EndA, EndB)
但要实施Min()
以及Max()
,您必须编写代码(使用c三进制表示简洁):(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)