Określ, Czy Dwa Zakresy Dat Nakładają Się Na Siebie

Biorąc pod uwagę dwa zakresy dat, jaki jest najprostszy lub najskuteczniejszy sposób określenia, czy oba zakresy dat nakładają się na siebie?

Jako przykład załóżmy, że mamy zakresy oznaczone zmiennymi DateTime StartDate1 do EndDate1 Oraz StartDate2 do EndDate2.

Author: David Faber, 2008-11-28

30 answers

(StartA = StartB)

dowód:
Niech ConditionA oznacza, że DateRange a całkowicie po DateRange B
_ |---- DateRange A ------| |---Date Range B -----| _
(True if StartA > EndB)

Niech ConditionB oznacza, że DateRange A jest całkowicie przed DateRange B
|---- DateRange A -----| _ _ |---Date Range B ----|
(True if EndA < StartB)

Wtedy zachodzi zbieżność, jeśli Ani a, ani B nie są prawdziwe -
(Jeśli jeden zakres nie jest ani całkowicie po drugim,
ani całkowicie przed drugą, wtedy muszą się pokrywać.)

Teraz jedno z praw De Morgana mówi, że:

Not (A Or B) Not A And Not B

Co tłumaczy się na: (StartA <= EndB) and (EndA >= StartB)


Uwaga: obejmuje to warunki, w których krawędzie nakładają się dokładnie. Jeśli chcesz to wykluczyć,
Zmień operatory >= na > i <= na <


NOTE2. Dzięki @Baodad, zobacz ten blog , rzeczywiste nakładanie się jest najmniej:
{ endA-startA, endA - startB, endB-startA, endB - startB }

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


NOTE3. Dzięki @ tomosius, krótsza wersja czyta:
DateRangesOverlap = max(start1, start2) < min(end1, end2)
W rzeczywistości jest to skrót składniowy dla dłuższej implementacji, który zawiera dodatkowe kontrole w celu sprawdzenia, czy daty rozpoczęcia są na lub przed datami końcowymi. Wyprowadzenie tego z góry:

Jeśli daty rozpoczęcia i zakończenia mogą być nie w porządku, tzn. jeśli jest to możliwe, że startA > endA lub startB > endB, to musisz również sprawdzić, czy są w porządku, więc oznacza to, że musisz dodać dwie dodatkowe Zasady ważności:
(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB) lub:
(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB) lub,
(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB)) lub:
(Max(StartA, StartB) <= Min(EndA, EndB)

Ale aby zaimplementować Min() i Max(), musisz kodować, (używając C ternary dla terseness),:
(StartA > StartB? Start A: StartB) <= (EndA < EndB? EndA: EndB)

 1913
Author: Charles Bretana,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-09 13:46:01

Uważam, że wystarczy powiedzieć, że oba zakresy nakładają się, jeśli:

(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)
 328
Author: Ian Nelson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-11-28 15:01:25

Ten artykuł biblioteka okresów czasu dla. NET opisuje związek dwóch okresów za pomocą wyliczenia PeriodRelation :

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

Tutaj wpisz opis obrazka

 92
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-05-29 08:03:33

Dla rozumowania o relacjach czasowych (lub dowolnych innych relacjach interwałowych), rozważ algebrę Interwałową Allena. Opisuje 13 możliwych relacji, które mogą mieć dwa przedziały względem siebie. Możesz znaleźć inne referencje - "interwał Allena" wydaje się być operacyjnym terminem wyszukiwania. Można również znaleźć informacje o tych operacjach w Snodgrass ' s Tworzenie aplikacji zorientowanych na czas w SQL (PDF dostępny online pod adresem URL), a w Date, Darwen and Lorentzos Temporal Data and the Relational Model (2002) lub Time and Relational Theory: Temporal Databases in the Relational Model and SQL (2014; skutecznie drugie wydanie TD&RM).


Krótka (ish) odpowiedź brzmi: podane dwa przedziały daty A i B ze składnikami .start i .end oraz ograniczenie .start <= .end, wtedy dwa przedziały nakładają się, jeśli:

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

Możesz dostroić użycie >= vs > i <= vs <, aby spełnić swoje wymagania dotyczące stopnia nakładania się.


ErikE komentarze:

Możesz dostać tylko 13, jeśli policzysz rzeczy śmieszne... Mogę uzyskać "15 możliwych relacji, które mogą mieć dwa interwały", gdy oszaleję z tym. Przez rozsądne liczenie dostaję tylko sześć, a jeśli wyrzucisz to, czy A czy B jest pierwsze, dostaję tylko trzy (bez intersektu, częściowo intersektu, jeden całkowicie w innym). 15 idzie tak: [przed: przed, początek, wewnątrz, koniec, po], [początek: początek, wewnątrz, koniec, after], [within: within, end, after], [end: end, after], [after:after].

Myślę, że nie można zliczyć dwóch wpisów "before: before" I "after: after". Mógłbym zobaczyć 7 wpisów, jeśli zrównasz pewne relacje z ich odwrotnościami (Patrz diagram w odnośnym URL Wikipedii; ma 7 wpisów, z których 6 ma inną odwrotność, z równymi nie mającymi odrębnej odwrotności). A to, czy trzy jest rozsądne, zależy od twoich wymagań.

----------------------|-------A-------|----------------------
    |----B1----|
           |----B2----|
               |----B3----|
               |----------B4----------|
               |----------------B5----------------|
                      |----B6----|
----------------------|-------A-------|----------------------
                      |------B7-------|
                      |----------B8-----------|
                         |----B9----|
                         |----B10-----|
                         |--------B11--------|
                                      |----B12----|
                                         |----B13----|
----------------------|-------A-------|----------------------
 68
Author: Jonathan Leffler,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-21 07:44:31

Jeśli samo nakładanie się powinno być również obliczone, możesz użyć następującego wzoru:

overlap = max(0, min(EndDate1, EndDate2) - max(StartDate1, StartDate2))
if (overlap > 0) { 
    ...
}
 25
Author: Vitalii Fedorenko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-09-06 02:07:10

Wszystkie rozwiązania, które sprawdzają wiele warunków na podstawie tego, gdzie zakresy są względem siebie, można znacznie uprościć przez po prostu upewniając się, że określony zakres zaczyna się wcześniej! upewnij się, że pierwszy zakres zaczyna się wcześniej (lub w tym samym czasie), zamieniając zakresy, jeśli to konieczne, z góry.

Następnie można wykryć nakładanie się, jeśli drugi początek zakresu jest mniejszy lub równy pierwszemu końcowi zakresu (jeśli zakresy są włączone, zawierające zarówno Początek, jak i koniec razy) lub mniej niż (Jeśli zakresy obejmują początek i koniec).

Zakładając, że na obu końcach są tylko cztery możliwości, z których jedna jest nie pokrywająca się:

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

Punkt końcowy z zakresu 2 nie wchodzi do niego. Więc w pseudo-kodzie:

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

Można to jeszcze bardziej uprościć do:

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

Jeśli zakresy są inclusive na początku i exclusive na końcu, wystarczy zastąpić > >= w drugim if poleceniu (dla pierwszy segment kodu: w drugim segmencie kodu użyjesz < zamiast <=):

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

Znacznie ograniczasz liczbę kontroli, które musisz wykonać, ponieważ usuwasz połowę miejsca problemu wcześniej, upewniając się, że zakres 1 nigdy nie zaczyna się po zakresie 2.

 16
Author: paxdiablo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-17 09:00:11

Oto kolejne rozwiązanie wykorzystujące JavaScript. Specjalności mojego rozwiązania:

  • obsługuje wartości null jako nieskończoność
  • zakłada, że dolna granica jest inkluzywna, a górna wyłączna.
  • pochodzi z kilku testów

Testy są oparte na liczbach całkowitych, ale ponieważ obiekty date w JavaScript są porównywalne, możesz po prostu wrzucić dwa obiekty date. Albo możesz dorzucić milisekundę znacznik czasu.

Kod:

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

Testy:

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

Wynik po uruchomieniu z karma&jasmine&PhantomJS:

PhantomJS 1.9.8 (Linux): wykonano 20 z 20 sukcesów (0.003 sek. / 0.004 sek.)
 13
Author: yankee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-13 13:19:48

Wiem, że zostało to otagowane jako język-agnostyczny, ale dla wszystkich implementujących w Javie: Nie wymyślajcie koła na nowo i używajcie czasu Joda.

Http://joda-time.sourceforge.net/api-release/org/joda/time/base/AbstractInterval.html#overlaps(org.joda.time.ReadableInterval)

 8
Author: Stefan Haberl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-13 15:10:59

Zrobiłbym

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

Gdzie IsBetween jest czymś w rodzaju

    public static bool IsBetween(this DateTime value, DateTime left, DateTime right) {
        return (value > left && value < right) || (value < left && value > right);
    }
 7
Author: Bob,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-07-27 14:09:53

Opublikowane tutaj rozwiązanie nie działało dla wszystkich nakładających się zakresów...

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

Moje rozwiązanie robocze brzmiało:

AND (
  ('start_date' BETWEEN STARTDATE AND ENDDATE) -- caters for inner and end date outer
  OR
  ('end_date' BETWEEN STARTDATE AND ENDDATE) -- caters for inner and start date outer
  OR
  (STARTDATE BETWEEN 'start_date' AND 'end_date') -- only one needed for outer range where dates are inside.
) 
 5
Author: on_,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-11-05 08:24:53

Oto moje rozwiązanie wJava , które działa również na nieograniczonych interwałach

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));
}
 5
Author: Khaled.K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-05 09:11:24

To było moje rozwiązanie javascript z momentem.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;
 4
Author: Ignacio Pascual,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-12 20:28:36

Tutaj wpisz opis obrazka

Oto kod, który robi magię:

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

Gdzie.

  • A - > 1Start
  • B - > 1End
  • C - > 2Start
  • D - > 2End
Dowód? Sprawdź ten test console code gist .
 4
Author: sandeep talabathula,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-28 18:52:24

W przypadku, gdy używasz zakresu dat, który jeszcze się nie zakończył (nadal trwa) np. nie ustawiony endDate = '0000-00-00' nie można używać pomiędzy, ponieważ 0000-00-00 nie jest poprawną datą!

Użyłem tego rozwiązania:

(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

Jeśli startdate2 jest wyższy niż enddate nie ma nakładania się!

 2
Author: jack,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-27 17:12:30

Najprostszy

Najprostszym sposobem jest użycie dobrze zaprojektowanej dedykowanej biblioteki do pracy w czasie.

someInterval.overlaps( anotherInterval )

Java.time & ThreeTen-Extra

Najlepszy w branży jest java.time framework Wbudowany W Java 8 i nowsze. Dodaj do tego ThreeTen-Extra projekt, który uzupełnia Javę.czas z dodatkowymi zajęciami, w szczególności Interval Klasa, której potrzebujemy.

Jeśli chodzi o tag language-agnostic w tym pytaniu, kod źródłowy obu projektów jest dostępny do użytku w innych językach (należy pamiętać o ich licencjach).

Interval

The org.threeten.extra.Interval klasa jest przydatna, ale wymaga momentów date-time (java.time.Instant objects), a nie tylko wartości date. Więc kontynuujemy, używając pierwszej chwili dnia w UTC, aby reprezentować datę.

Instant start = Instant.parse( "2016-01-01T00:00:00Z" );
Instant stop = Instant.parse( "2016-02-01T00:00:00Z" );

Utwórz Interval, aby reprezentować ten okres czasu.

Interval interval_A = Interval.of( start , stop );

Możemy również zdefiniować {[6] } z momentem początkowym plus Duration.

Instant start_B = Instant.parse( "2016-01-03T00:00:00Z" );
Interval interval_B = Interval.of( start_B , Duration.of( 3 , ChronoUnit.DAYS ) );

Porównanie do testu na nakładanie się jest łatwe.

Boolean overlaps = interval_A.overlaps( interval_B );

Możesz porównać Interval przeciw innym Interval lub Instant:

Wszystkie z nich wykorzystują podejście Half-Open do zdefiniowania zakresu czas, w którym początek jest inclusive , a zakończenie jest exclusive .

 2
Author: Basil Bourque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-04 23:30:07

To jest rozszerzenie do doskonała odpowiedź przez @charles-bretana.

Odpowiedź nie rozróżnia jednak między przedziałami otwartymi, zamkniętymi i półotwartymi (lub półotwartymi).

Przypadek 1: A, B są zamkniętymi interwałami

A = [StartA, EndA]
B = [StartB, EndB]

                         [---- DateRange A ------]   (True if StartA > EndB)
[--- Date Range B -----]                           


[---- DateRange A -----]                             (True if EndA < StartB)
                         [--- Date Range B ----]

Nakładka iff: (StartA <= EndB) and (EndA >= StartB)

Przypadek 2: A, B są interwałami otwartymi

A = (StartA, EndA)
B = (StartB, EndB)

                         (---- DateRange A ------)   (True if StartA >= EndB)
(--- Date Range B -----)                           

(---- DateRange A -----)                             (True if EndA <= StartB)
                         (--- Date Range B ----)

Nakładka iff: (StartA < EndB) and (EndA > StartB)

Case 3 : A, B right open

A = [StartA, EndA)
B = [StartB, EndB)

                         [---- DateRange A ------)   (True if StartA >= EndB) 
[--- Date Range B -----)                           

[---- DateRange A -----)                             (True if EndA <= StartB)
                         [--- Date Range B ----)

Warunek nakładania się: (StartA < EndB) and (EndA > StartB)

Przypadek 4: A, B otwarte

A = (StartA, EndA]
B = (StartB, EndB]

                         (---- DateRange A ------]   (True if StartA >= EndB)
(--- Date Range B -----]                           

(---- DateRange A -----]                             (True if EndA <= StartB)
                         (--- Date Range B ----]

Warunek nakładania się: (StartA < EndB) and (EndA > StartB)

Przypadek 5 : a prawy otwarty, B zamknięty

A = [StartA, EndA)
B = [StartB, EndB]

                         [---- DateRange A ------)    (True if StartA > EndB)
[--- Date Range B -----]                           


[---- DateRange A -----)                              (True if EndA <= StartB)  
                         [--- Date Range B ----]

Warunek nakładania się: (StartA <= EndB) and (EndA > StartB)

Itd...

Wreszcie, ogólnym warunkiem nakładania się dwóch przedziałów jest

(StartA StartB)

Gdzie zamienia nierówność ścisłą w nierównomierną, gdy porównuje się dwie zawarte punkt końcowy.

 2
Author: user2314737,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-14 19:06:23

Oto ogólna metoda, która może być użyteczna lokalnie.

    // Takes a list and returns all records that have overlapping time ranges.
    public static IEnumerable<T> GetOverlappedTimes<T>(IEnumerable<T> list, Func<T, bool> filter, Func<T,DateTime> start, Func<T, DateTime> end)
    {
        // Selects all records that match filter() on left side and returns all records on right side that overlap.
        var overlap = from t1 in list
                      where filter(t1)
                      from t2 in list
                      where !object.Equals(t1, t2) // Don't match the same record on right side.
                      let in1 = start(t1)
                      let out1 = end(t1)
                      let in2 = start(t2)
                      let out2 = end(t2)
                      where in1 <= out2 && out1 >= in2
                      let totover = GetMins(in1, out1, in2, out2)
                      select t2;

        return overlap;
    }

    public static void TestOverlap()
    {
        var tl1 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 1:00pm".ToDate(), Out = "1/1/08 4:00pm".ToDate() };
        var tl2 = new TempTimeEntry() { ID = 2, Name = "John", In = "1/1/08 5:00pm".ToDate(), Out = "1/1/08 6:00pm".ToDate() };
        var tl3 = new TempTimeEntry() { ID = 3, Name = "Lisa", In = "1/1/08 7:00pm".ToDate(), Out = "1/1/08 9:00pm".ToDate() };
        var tl4 = new TempTimeEntry() { ID = 4, Name = "Joe", In = "1/1/08 3:00pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
        var tl5 = new TempTimeEntry() { ID = 1, Name = "Bill", In = "1/1/08 8:01pm".ToDate(), Out = "1/1/08 8:00pm".ToDate() };
        var list = new List<TempTimeEntry>() { tl1, tl2, tl3, tl4, tl5 };
        var overlap = GetOverlappedTimes(list, (TempTimeEntry t1)=>t1.ID==1, (TempTimeEntry tIn) => tIn.In, (TempTimeEntry tOut) => tOut.Out);

        Console.WriteLine("\nRecords overlap:");
        foreach (var tl in overlap)
            Console.WriteLine("Name:{0} T1In:{1} T1Out:{2}", tl.Name, tl.In, tl.Out);
        Console.WriteLine("Done");

        /*  Output:
            Records overlap:
            Name:Joe T1In:1/1/2008 3:00:00 PM T1Out:1/1/2008 8:00:00 PM
            Name:Lisa T1In:1/1/2008 7:00:00 PM T1Out:1/1/2008 9:00:00 PM
            Done
         */
    }
 1
Author: staceyw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-04-13 05:14:50

W Microsoft SQL SERVER-funkcja 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
 1
Author: Prasenjit Banerjee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-05 13:49:48
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");
            }
 1
Author: mmarjeh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-18 17:12:05

Używanie Java util.Data, oto co zrobiłem.

    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;
    }
 1
Author: Shehan Simen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-06 05:21:51

Najprostszym sposobem, aby to zrobić, moim zdaniem byłoby porównanie, czy któreś EndDate1 jest przed StartDate2 i EndDate2 jest przed StartDate1.

To oczywiście, jeśli rozważasz interwały, w których StartDate jest zawsze przed EndDate.

 1
Author: AlexDrenea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-19 14:10:52

Miałem sytuację, w której mieliśmy daty zamiast dat, A daty mogły pokrywać się tylko na początku/końcu. Przykład poniżej:

Tutaj wpisz opis obrazka

(Zielony jest aktualnym interwałem, niebieskie bloki są poprawnymi interwałami, czerwone są nakładającymi się interwałami).

Zaadaptowałem odpowiedź Iana Nelsona na następujące rozwiązanie:

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

To pasuje do wszystkich przypadków nakładania się, ale ignoruje dozwolone przypadki nakładania się.

 1
Author: Gus,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-18 15:46:58

Rozwiązanie matematyczne podane przez @ Bretana jest dobre, ale pomija dwa konkretne szczegóły:

  1. aspekt zamkniętych lub półotwartych interwałów
  2. puste odstępy

O zamkniętym lub otwartym stanie granic interwałów, rozwiązanie @ Bretana valid dla zamkniętych interwałów

(StartA = StartB)

Można przepisać dla interwałów półotwartych do:

(StartA StartB)

Ta korekta jest konieczna, ponieważ otwarta granica interwału nie należy z definicji do zakresu wartości interwału.


I O pustych interwałach, cóż, tutaj relacja pokazana powyżej nie trzyma się. Puste interwały, które nie zawierają żadnej ważnej wartości z definicji, muszą być traktowane jako szczególny przypadek. Zademonstruję to za pomocą mojej biblioteki czasu Java Time4J na poniższym przykładzie:

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)

Wspornik kwadratowy prowadzący "["oznacza zamknięty początek, podczas gdy ostatni nawias") " oznacza otwarty koniec.

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

Jak pokazano powyżej, puste interwały naruszają powyższy warunek nakładania się (szczególnie startA

 1
Author: Meno Hochschild,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-10 05:56:52
if (StartDate1 > StartDate2) swap(StartDate, EndDate);

(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1);
 0
Author: Syam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-23 07:23:20

Podziel problem na przypadki, a następnie obsłuż każdą sprawę.

Sytuacja "przecinają się dwa zakresy dat" obejmuje dwa przypadki - pierwszy zakres dat rozpoczyna się w drugim, lub drugi zakres dat rozpoczyna się w pierwszym.

 0
Author: Colonel Panic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-10-12 23:17:53

Możesz spróbować tego:

//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);
 0
Author: Ilya,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-25 14:02:53

To było moje rozwiązanie, zwraca true, gdy wartości nie nakładają się na siebie:

X START 1 Y END 1

A START 2 B END 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
 0
Author: Fez Vrasta,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-27 15:26:41

Dla ruby znalazłem również to:

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

Znalazłem to tutaj z ładnym wyjaśnieniem -> http://makandracards.com/makandra/984-test-if-two-date-ranges-overlap-in-ruby-or-rails

 0
Author: mahatmanich,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-24 23:40:45

Poniżej znajduje się identyfikator, dla którego podany zakres dat (daty rozpoczęcia i zakończenia pokrywają się z którąkolwiek z dat (daty rozpoczęcia i zakończenia) w mojej table_name

select id from table_name where (START_DT_TM >= 'END_DATE_TIME'  OR   
(END_DT_TM BETWEEN 'START_DATE_TIME' AND 'END_DATE_TIME'))
 0
Author: Shravan Ramamurthy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-01-19 21:57:31

Odpowiedź jest dla mnie zbyt prosta, więc stworzyłem bardziej ogólne dynamiczne polecenie SQL, które sprawdza, czy dana osoba ma jakieś nakładające się daty.

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)
 0
Author: Tom McDonough,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-09 16:16:33