给定两个日期范围,确定两个日期是否重叠的最简单或最有效的方法是什么?
例如,假设我们有由DateTime变量StartDate1到EndDate1和StartDate2到EndDate2表示的范围。
给定两个日期范围,确定两个日期是否重叠的最简单或最有效的方法是什么?
例如,假设我们有由DateTime变量StartDate1到EndDate1和StartDate2到EndDate2表示的范围。
当前回答
最简单的
最简单的方法是使用精心设计的专用库进行日期时间工作。
someInterval.overlaps( anotherInterval )
java.time&ThreeTen额外
业务中最好的是内置在Java8和更高版本中的java.time框架。添加ThreeTen Extra项目,该项目用额外的类来补充java.time,特别是我们这里需要的Interval类。
至于这个问题上的语言不可知标签,两个项目的源代码都可以在其他语言中使用(注意它们的许可证)。
间隔
org.threeten.extra.Interval类很方便,但需要日期时间瞬间(java.time.Instant对象),而不是仅日期值。因此,我们继续使用UTC中的一天的第一刻来表示日期。
Instant start = Instant.parse( "2016-01-01T00:00:00Z" );
Instant stop = Instant.parse( "2016-02-01T00:00:00Z" );
创建一个间隔来表示该时间跨度。
Interval interval_A = Interval.of( start , stop );
我们也可以用开始时刻加上持续时间来定义间隔。
Instant start_B = Instant.parse( "2016-01-03T00:00:00Z" );
Interval interval_B = Interval.of( start_B , Duration.of( 3 , ChronoUnit.DAYS ) );
比较和测试重叠很容易。
Boolean overlaps = interval_A.overlaps( interval_B );
您可以将“间隔”与另一个“间隔”或“即时”进行比较:
邻接,邻接包含外壳等于在之后是之前重叠,重叠
所有这些都使用半开放的方法来定义一段时间,其中开始是包容性的,结束是排他性的。
其他回答
最简单的
最简单的方法是使用精心设计的专用库进行日期时间工作。
someInterval.overlaps( anotherInterval )
java.time&ThreeTen额外
业务中最好的是内置在Java8和更高版本中的java.time框架。添加ThreeTen Extra项目,该项目用额外的类来补充java.time,特别是我们这里需要的Interval类。
至于这个问题上的语言不可知标签,两个项目的源代码都可以在其他语言中使用(注意它们的许可证)。
间隔
org.threeten.extra.Interval类很方便,但需要日期时间瞬间(java.time.Instant对象),而不是仅日期值。因此,我们继续使用UTC中的一天的第一刻来表示日期。
Instant start = Instant.parse( "2016-01-01T00:00:00Z" );
Instant stop = Instant.parse( "2016-02-01T00:00:00Z" );
创建一个间隔来表示该时间跨度。
Interval interval_A = Interval.of( start , stop );
我们也可以用开始时刻加上持续时间来定义间隔。
Instant start_B = Instant.parse( "2016-01-03T00:00:00Z" );
Interval interval_B = Interval.of( start_B , Duration.of( 3 , ChronoUnit.DAYS ) );
比较和测试重叠很容易。
Boolean overlaps = interval_A.overlaps( interval_B );
您可以将“间隔”与另一个“间隔”或“即时”进行比较:
邻接,邻接包含外壳等于在之后是之前重叠,重叠
所有这些都使用半开放的方法来定义一段时间,其中开始是包容性的,结束是排他性的。
这里是我的简化。假设时间间隔
| |
| |
不要重叠,xa<xb和ya<yb可以简化处理。上述条件可以简单检查。然后你会得到
ya yb
|--------|
xa |--|xb
|----|
|----|
ya > xa => return ya - xa < xb - xa
else => return xa < yb
正如您可能注意到的,第二个间隔仅在xa>=ya的情况下相关。
在Microsoft SQL SERVER中-SQL函数
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
记住解决方案的一个简单方法是最小(结束)>最大(开始)
如果您使用的日期范围尚未结束(仍在进行中),例如未设置endDate='0000-00-00'您不能使用BETWEEN,因为0000-00-00不是有效日期!
我使用了这个解决方案:
(Startdate BETWEEN '".$startdate2."' AND '".$enddate2."') //overlap: starts between start2/end2
OR (Startdate < '".$startdate2."'
AND (enddate = '0000-00-00' OR enddate >= '".$startdate2."')
) //overlap: starts before start2 and enddate not set 0000-00-00 (still on going) or if enddate is set but higher then startdate2
如果startdate2高于enddate,则没有重叠!