etc./StackOverFlow

두 날짜 범위가 겹치는지 여부 확인

청렴결백한 만능 재주꾼 2023. 4. 9. 15:43
반응형

질문자 :Ian Nelson


두 날짜 범위가 주어진 경우 두 날짜 범위가 겹치는지 여부를 확인하는 가장 간단하거나 가장 효율적인 방법은 무엇입니까?

StartDate1 ~ EndDate1 StartDate2 ~ EndDate2 로 표시된 범위가 있다고 가정합니다.



(StartA <= EndB) 및 (EndA >= StartB)

증거:
ConditionA는 DateRange B 이후의 DateRange A를 의미합니다.

 _ |---- DateRange A ------| |---Date Range B -----| _

StartA > EndB 경우 참)

ConditionB는 DateRange A가 DateRange B보다 완전히 이전임을 의미합니다.

 |---- DateRange A -----| _ _ |---Date Range B ----|

EndA < StartB 경우 참)

그러면 A도 B도 모두 참이 아닌 경우 중첩이 존재합니다.
(한 범위가 다른 범위 뒤에 완전히 있지 않은 경우
또는 완전히 다른 것보다 먼저 겹쳐야 합니다.)

이제 De Morgan의 법칙 중 하나는 다음과 같이 말합니다.

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)
이것은 실제로 시작 날짜가 endDates 또는 그 이전인지 확인하기 위한 추가 검사를 포함하는 더 긴 구현에 대한 구문상의 지름길입니다. 위에서 이것을 유도하면 다음과 같습니다.

시작 날짜와 종료 날짜가 순서가 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)


Charles Bretana

다음과 같은 경우 두 범위가 겹치는 것으로 충분하다고 생각합니다.

 (StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)

Ian Nelson

이 기사 .NET용 Time Period Library는 PeriodRelation 열거로 두 기간의 관계를 설명합니다.

 // ------------------------------------------------------------------------ public enum PeriodRelation { After, StartTouching, StartInside, InsideStartTouching, EnclosingStartTouching, Enclosing, EnclosingEndTouching, ExactMatch, Inside, InsideEndTouching, EndInside, EndTouching, Before, } // enum PeriodRelation 

여기에 이미지 설명 입력


user687474

시간 관계(또는 다른 간격 관계)에 대한 추론을 위해 Allen's Interval Algebra 를 고려하십시오. 두 구간이 서로에 대해 가질 수 있는 13가지 가능한 관계를 설명합니다. 다른 참조를 찾을 수 있습니다. "Allen Interval"은 작동하는 검색어인 것 같습니다. Snodgrass의 SQL에서 시간 지향 응용 프로그램 개발 (PDF는 URL에서 온라인 제공), Date, Darwen 및 Lorentzos Temporal Data and the Relational Model (2002) 또는 Time and Relational Theory: Temporal Databases in에서 이러한 작업에 대한 정보를 찾을 수도 있습니다. 관계형 모델 및 SQL (2014; 사실상 TD&RM의 두 번째 판).


짧은(ish) 대답은 .start.end 구성 요소 .start <= .end 제약 조건이 A 두 개의 날짜 간격 A와 B 가 주어지면 다음과 같은 경우 두 간격이 겹칩니다.

 A.end >= B.start AND A.start <= B.end

>=><=< 의 사용을 조정하여 중첩 정도에 대한 요구 사항을 충족할 수 있습니다.


ErikE 코멘트:

웃긴거 세어보면 13개밖에 안나오는데.. 미치면 "2구간이 가질 수 있는 15개의 관계"를 얻을 수 있다. 현명한 계산으로 나는 6개만 얻고, A가 먼저인지 B가 먼저인지 신경쓰지 않고 버리면 3개만 얻습니다(교차 없음, 부분적으로 교차, 하나는 완전히 다른 것 안에 있음). 15는 다음과 같이 진행됩니다: [이전:전, 시작, 내, 종료, 후], [시작: 시작, 내, 종료, 후], [내:내, 종료, 후], [종료:종료, 후], [ 후: 후].

'before:before'와 'after:after' 두 항목을 셀 수 없다고 생각합니다. 일부 관계를 역과 동일시하면 7개의 항목을 볼 수 있습니다(참조된 Wikipedia URL의 다이어그램 참조, 7개의 항목이 있으며 그 중 6개는 다른 역이 있고 등호에는 고유한 역이 없음). 그리고 세 가지가 합리적인지 여부는 요구 사항에 따라 다릅니다.

 ----------------------|-------A-------|---------------------- |----B1----| |----B2----| |----B3----| |----------B4----------| |----------------B5----------------| |----B6----| ----------------------|-------A-------|---------------------- |------B7-------| |----------B8-----------| |----B9----| |----B10-----| |--------B11--------| |----B12----| |----B13----| ----------------------|-------A-------|----------------------

Jonathan Leffler

겹침 자체도 계산해야 하는 경우 다음 공식을 사용할 수 있습니다.

 overlap = max(0, min(EndDate1, EndDate2) - max(StartDate1, StartDate2)) if (overlap > 0) { ... }

Vitalii Fedorenko

범위가 서로 관련되어 있는 위치를 기반으로 다양한 조건을 확인하는 모든 솔루션 은 특정 범위가 더 일찍 시작하도록 함으로써 크게 단순화할 수 있습니다! 필요한 경우 범위를 미리 교환하여 첫 번째 범위가 더 일찍(또는 동시에) 시작되도록 합니다.

그런 다음 다른 범위 시작이 첫 번째 범위 끝보다 작거나 같거나(범위가 포함된 경우 시작 및 종료 시간을 모두 포함하는 경우) 또는 보다 작은 경우(범위에 시작이 포함되고 끝이 제외된 경우) 중첩을 감지할 수 있습니다. .

양쪽 끝을 모두 포함한다고 가정하면 다음 중 하나가 겹치지 않을 가능성이 네 가지뿐입니다.

 |----------------------| range 1 |---> range 2 overlap |---> range 2 overlap |---> range 2 overlap |---> range 2 no overlap

범위 2의 끝점은 입력되지 않습니다. 따라서 의사 코드에서:

 def doesOverlap (r1, r2): if r1.s > r2.s: swap r1, r2 if r2.s > r1.e: return false return true

이것은 다음과 같이 훨씬 더 단순화될 수 있습니다.

 def doesOverlap (r1, r2): if r1.s > r2.s: swap r1, r2 return r2.s <= r1.e

범위가 끝에서 시작과 독점에 포함하는 경우, 당신은 교체해야 >>= 두 번째의 if 문 (첫 번째 코드 세그먼트 : 두 번째 코드 세그먼트에, 당신이 사용할 것 < 대신 <= ):

 |----------------------| range 1 |---> range 2 overlap |---> range 2 overlap |---> range 2 no overlap |---> range 2 no overlap

범위 1이 범위 2 이후에 시작되지 않도록 하여 문제 공간의 절반을 조기에 제거하기 때문에 확인해야 하는 수를 크게 제한합니다.


paxdiablo

JavaScript를 사용하는 또 다른 솔루션이 있습니다. 내 솔루션의 특기:

  • null 값을 무한대로 처리
  • 하한은 포함하고 상한은 배타적이라고 가정합니다.
  • 테스트의 무리와 함께 제공

테스트는 정수를 기반으로 하지만 JavaScript의 날짜 개체는 비교할 수 있으므로 두 날짜 개체도 넣을 수 있습니다. 또는 밀리초 타임스탬프를 입력할 수 있습니다.

암호:

 /** * 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); }

테스트:

 describe('', function() { function generateTest(firstRange, secondRange, expected) { it(JSON.stringify(firstRange) + ' and ' + JSON.stringify(secondRange), function() { expect(intervalsOverlap(firstRange[0], firstRange[1], secondRange[0], secondRange[1])).toBe(expected); }); } describe('no overlap (touching ends)', function() { generateTest([10,20], [20,30], false); generateTest([20,30], [10,20], false); generateTest([10,20], [20,null], false); generateTest([20,null], [10,20], false); generateTest([null,20], [20,30], false); generateTest([20,30], [null,20], false); }); describe('do overlap (one end overlaps)', function() { generateTest([10,20], [19,30], true); generateTest([19,30], [10,20], true); generateTest([10,20], [null,30], true); generateTest([10,20], [19,null], true); generateTest([null,30], [10,20], true); generateTest([19,null], [10,20], true); }); describe('do overlap (one range included in other range)', function() { generateTest([10,40], [20,30], true); generateTest([20,30], [10,40], true); generateTest([10,40], [null,null], true); generateTest([null,null], [10,40], true); }); describe('do overlap (both ranges equal)', function() { generateTest([10,20], [10,20], true); generateTest([null,20], [null,20], true); generateTest([10,null], [10,null], true); generateTest([null,null], [null,null], true); }); });

karma&jasmine&PhantomJS로 실행할 때의 결과:

PhantomJS 1.9.8(Linux): 20/20 SUCCESS 실행(0.003초 / 0.004초)


yankee

여기에 이미지 설명 입력

다음은 마법을 수행하는 코드입니다.

 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));

어디에..

  • A -> 1시작
  • B -> 1종료
  • C -> 2시작
  • D -> 2End

증거? 이 테스트 콘솔 코드 요지를 확인하십시오.


sandeep talabathula

무제한 간격에서도 작동하는 Java 의 내 솔루션은 다음과 같습니다.

 private Boolean overlap (Timestamp startA, Timestamp endA, Timestamp startB, Timestamp endB) { return (endB == null || startA == null || !startA.after(endB)) && (endA == null || startB == null || !endA.before(startB)); }

Khaled.K

난 그럴거야

 StartDate1.IsBetween(StartDate2, EndDate2) || EndDate1.IsBetween(StartDate2, EndDate2)

IsBetween 은 다음과 같습니다.

 public static bool IsBetween(this DateTime value, DateTime left, DateTime right) { return (value > left && value < right) || (value < left && value > right); }

Bob

솔루션을 기억하는 쉬운 방법은
min(ends)>max(starts)


Radacina

여기에 게시된 솔루션은 모든 겹치는 범위에서 작동하지 않았습니다...

 ----------------------|----------A-------|----------- -----------
    |----B1----|
           |----B2----|
               |----B3----|
               |------------B4----------|
               |----------------B5----------------|
                      |----B6----|
----------------------|----------A-------|----------- -----------
                      |---------B7-------|
                      |------------B8-----------|
                         |----B9----|
                         |----B10-----|
                         |--------B11--------|
                                      |----B12----|
                                         |----B13----|
----------------------|----------A-------|----------- -----------

내 작업 솔루션은 다음과 같습니다.

그리고 (
  ('start_date' BETWEEN STARTDATE AND ENDDATE) -- 내부 및 종료 날짜 외부 제공
  또는
  ('end_date' BETWEEN STARTDATE AND ENDDATE) -- 내부 및 시작 날짜 외부에 적합
  또는
  (STARTDATE BETWEEN 'start_date' AND 'end_date') -- 날짜가 내부에 있는 외부 범위에는 하나만 필요합니다.
) 

on_

이것은 moment.js를 사용한 자바스크립트 솔루션이었습니다.

 // Current row dates var dateStart = moment("2014-08-01", "YYYY-MM-DD"); var dateEnd = moment("2014-08-30", "YYYY-MM-DD"); // Check with dates above var rangeUsedStart = moment("2014-08-02", "YYYY-MM-DD"); var rangeUsedEnd = moment("2014-08-015", "YYYY-MM-DD"); // Range covers other ? if((dateStart <= rangeUsedStart) && (rangeUsedEnd <= dateEnd)) { return false; } // Range intersects with other start ? if((dateStart <= rangeUsedStart) && (rangeUsedStart <= dateEnd)) { return false; } // Range intersects with other end ? if((dateStart <= rangeUsedEnd) && (rangeUsedEnd <= dateEnd)) { return false; } // All good return true;

Ignacio Pascual

momentjs를 사용한 짧은 대답 :

 function isOverlapping(startDate1, endDate1, startDate2, endDate2){ return moment(startDate1).isSameOrBefore(endDate2) && moment(startDate2).isSameOrBefore(endDate1); }

답변은 위 답변을 기반으로 하지만 단축되었습니다.


Nitin Jadhav

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

Prasenjit Banerjee

가장 단순한

가장 간단한 방법은 날짜-시간 작업을 위해 잘 설계된 전용 라이브러리를 사용하는 것입니다.

 someInterval.overlaps( anotherInterval )

java.time 및 ThreeTen-Extra

업계 최고는 Java 8 이상에 내장된 java.time 여기에 추가 클래스, 특히 여기에 필요한 Interval 클래스로 java.time을 보완하는 ThreeTen-Extra 프로젝트를 추가하십시오.

이 질문의 language-agnostic 태그의 경우 두 프로젝트의 소스 코드를 다른 언어로 사용할 수 있습니다(라이선스에 유의).

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 interval_A = Interval.of( start , stop );

시작 순간에 Duration Interval 을 정의할 수도 있습니다.

 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 );

Interval 을 다른 Interval 또는 Instant 와 비교할 수 있습니다.

이들 모두는 시작이 포함 되고 끝이 배타적인 시간 범위를 정의 Half-Open 접근 방식을 사용합니다.


Basil Bourque

@Bretana가 제공하는 수학적 솔루션은 훌륭하지만 두 가지 특정 세부 사항을 무시합니다.

  1. 폐쇄 또는 반 개방 간격의 측면
  2. 빈 간격

간격 경계의 닫힌 상태 또는 열린 상태에 대해 닫힌 간격에 유효한 @Bretana 솔루션

(StartA <= EndB) 및 (EndA >= StartB)

반개방 간격에 대해 다음과 같이 다시 작성할 수 있습니다.

(StartA < EndB) 및 (EndA > StartB)

열린 구간 경계는 정의에 따라 구간의 값 범위에 속하지 않기 때문에 이 수정이 필요합니다.


그리고 빈 간격 에 대해서는 위에 표시된 관계가 유지되지 않습니다. 정의에 따라 유효한 값을 포함하지 않는 빈 간격은 특별한 경우로 처리해야 합니다. 이 예제를 통해 Java 시간 라이브러리 Time4J로 시연합니다.

 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)

선행 대괄호 "["는 닫힌 시작을 나타내고 마지막 대괄호 ")"는 열린 끝을 나타냅니다.

 System.out.println( "startA < endB: " + a.getStartAsInstant().isBefore(b.getEndAsInstant())); // false System.out.println( "endA > startB: " + a.getEndAsInstant().isAfter(b.getStartAsInstant())); // true System.out.println("a overlaps b: " + a.intersects(b)); // a overlaps b: false

위에 표시된 것처럼 빈 간격은 위의 겹침 조건(특히 startA < endB)을 위반하므로 Time4J(및 다른 라이브러리도 마찬가지)는 임의의 간격이 빈 간격과 겹치는 것을 보장하기 위해 특별한 경우로 처리해야 합니다. 존재하지 않는다. 물론 날짜 간격(Time4J에서는 기본적으로 닫혀 있지만 빈 날짜 간격처럼 반쯤 열릴 수도 있음)은 비슷한 방식으로 처리됩니다.


Meno Hochschild

이것은 @charles-bretana 의 훌륭한 답변 에 대한 확장입니다.

그러나 대답은 개방, 폐쇄 및 반 개방(또는 반 폐쇄) 간격을 구분하지 않습니다.

사례 1 : 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 ----]

겹침 iff: (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 ----)

겹침 iff: (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 ----]

겹침 조건: (StartA <= EndB) and (EndA > StartB)

등...

마지막으로 두 구간이 겹치는 일반적인 조건은 다음과 같습니다.

(StartA < EndB) 및 (EndA > StartB)

포함된 두 끝점을 비교할 때마다 엄격한 부등식을 비엄격한 부등식으로 바꿉니다.


user2314737

다른 언어와 환경에 대한 여러 답변이 있으므로 여기에 표준 ANSI SQL에 대한 답변이 있습니다.

표준 SQL에서는 다음과 같이 간단합니다.

 (StartDate1, EndDate1) overlaps (StartDate2, EndDate2)

네 개의 열이 모두 DATE 또는 TIMESTAMP 열이라고 가정합니다. DATE 하나 이상 있으면 true를 반환합니다(DATE 값 가정).

(단, 모든 DBMS 제품이 지원하는 것은 아닙니다.)


PostgreSQL에서는 날짜 범위 를 사용하여 포함 여부 를 쉽게 테스트할 수도 있습니다.

 daterange(StartDate1, EndDate1) @> daterange(StartDate2, EndDate2)

위는 두 번째 범위가 첫 번째 범위에 완전히 포함된 경우 true를 반환합니다("겹침"과 다름).


a_horse_with_no_name

아직 끝나지 않은 날짜 범위를 사용하는 경우(예: not set endDate = '0000-00-00') 0000-00-00은 유효한 날짜가 아니기 때문에 BETWEEN을 사용할 수 없습니다!

이 솔루션을 사용했습니다.

 (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보다 높으면 겹치지 않습니다!


jack

대답은 나에게 너무 간단하므로 사람이 겹치는 날짜가 있는지 확인하는보다 일반적인 동적 SQL 문을 만들었습니다.

 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)

Tom McDonough

Java util.Date를 사용하여 여기에서 내가 한 일.

 public static boolean checkTimeOverlaps(Date startDate1, Date endDate1, Date startDate2, Date endDate2) { if (startDate1 == null || endDate1 == null || startDate2 == null || endDate2 == null) return false; if ((startDate1.getTime() <= endDate2.getTime()) && (startDate2.getTime() <= endDate1.getTime())) return true; return false; }

Shehan Simen

내 생각에 가장 쉬운 방법은 EndDate1이 StartDate2 이전이고 EndDate2가 StartDate1 이전인지 비교하는 것입니다.

물론 StartDate가 항상 EndDate보다 앞서는 간격을 고려하는 경우입니다.


AlexDrenea

날짜 시간 대신 날짜가 있고 날짜가 시작/종료에만 겹칠 수 있는 상황이 있었습니다. 아래 예:

여기에 이미지 설명 입력

(녹색은 현재 간격, 파란색 블록은 유효한 간격, 빨간색 블록은 겹치는 간격).

Ian Nelson의 답변을 다음 솔루션에 적용했습니다.

 (startB <= startA && endB > startA) || (startB >= startA && startB < endA)

이것은 모든 겹침 사례와 일치하지만 허용된 겹침 사례는 무시합니다.


Gus

문제를 케이스로 분할한 다음 각 케이스를 처리합니다 .

'두 날짜 범위가 교차'하는 상황은 첫 번째 날짜 범위가 두 번째 범위 내에서 시작하거나 두 번째 날짜 범위가 첫 번째 범위 내에서 시작하는 두 가지 경우에 적용됩니다.


Colonel Panic

당신은 이것을 시도할 수 있습니다:

 //custom date for example $d1 = new DateTime("2012-07-08"); $d2 = new DateTime("2012-07-11"); $d3 = new DateTime("2012-07-08"); $d4 = new DateTime("2012-07-15"); //create a date period object $interval = new DateInterval('P1D'); $daterange = iterator_to_array(new DatePeriod($d1, $interval, $d2)); $daterange1 = iterator_to_array(new DatePeriod($d3, $interval, $d4)); array_map(function($v) use ($daterange1) { if(in_array($v, $daterange1)) print "Bingo!";}, $daterange);

Ilya

public static class NumberExtensionMethods { public static Boolean IsBetween(this Int64 value, Int64 Min, Int64 Max) { if (value >= Min && value <= Max) return true; else return false; } public static Boolean IsBetween(this DateTime value, DateTime Min, DateTime Max) { Int64 numricValue = value.Ticks; Int64 numericStartDate = Min.Ticks; Int64 numericEndDate = Max.Ticks; if (numricValue.IsBetween(numericStartDate, numericEndDate) ) { return true; } return false; } } public static Boolean IsOverlap(DateTime startDate1, DateTime endDate1, DateTime startDate2, DateTime endDate2) { Int64 numericStartDate1 = startDate1.Ticks; Int64 numericEndDate1 = endDate1.Ticks; Int64 numericStartDate2 = startDate2.Ticks; Int64 numericEndDate2 = endDate2.Ticks; if (numericStartDate2.IsBetween(numericStartDate1, numericEndDate1) || numericEndDate2.IsBetween(numericStartDate1, numericEndDate1) || numericStartDate1.IsBetween(numericStartDate2, numericEndDate2) || numericEndDate1.IsBetween(numericStartDate2, numericEndDate2)) { return true; } return false; } if (IsOverlap(startdate1, enddate1, startdate2, enddate2)) { Console.WriteLine("IsOverlap"); }

mmarjeh

이것은 내 솔루션이었고 값이 겹치지 않으면 true를 반환합니다.

X 시작 1 Y 종료 1

A 시작 2 B 끝 2

 TEST1: (X <= A || X >= B) && TEST2: (Y >= B || Y <= A) && TEST3: (X >= B || Y <= A) X-------------Y A-----B TEST1: TRUE TEST2: TRUE TEST3: FALSE RESULT: FALSE --------------------------------------- X---Y A---B TEST1: TRUE TEST2: TRUE TEST3: TRUE RESULT: TRUE --------------------------------------- X---Y A---B TEST1: TRUE TEST2: TRUE TEST3: TRUE RESULT: TRUE --------------------------------------- X----Y A---------------B TEST1: FALSE TEST2: FALSE TEST3: FALSE RESULT: FALSE

Fez Vrasta

루비의 경우 다음도 찾았습니다.

 class Interval < ActiveRecord::Base validates_presence_of :start_date, :end_date # Check if a given interval overlaps this interval def overlaps?(other) (start_date - other.end_date) * (other.start_date - end_date) >= 0 end # Return a scope for all interval overlapping the given interval, including the given interval itself named_scope :overlapping, lambda { |interval| { :conditions => ["id <> ? AND (DATEDIFF(start_date, ?) * DATEDIFF(?, end_date)) >= 0", interval.id, interval.end_date, interval.start_date] }} end

좋은 설명과 함께 여기에서 찾았습니다 -> http://makandracards.com/makandra/984-test-if-two-date-ranges-overlap-in-ruby-or-rails


mahatmanich

아래 쿼리는 제공된 날짜 범위(시작 및 종료 날짜가 내 table_name의 날짜(시작 및 종료 날짜)와 겹치는 ID)를 제공합니다.

 select id from table_name where (START_DT_TM >= 'END_DATE_TIME' OR (END_DT_TM BETWEEN 'START_DATE_TIME' AND 'END_DATE_TIME'))

Shravan Ramamurthy

출처 : http:www.stackoverflow.com/questions/325933/determine-whether-two-date-ranges-overlap

반응형