Określ, czy dwa zakresy dat pokrywają się
Biorąc pod uwagę dwa zakresy dat, jaki jest najprostszy lub najskuteczniejszy sposób określenia, czy te dwa zakresy się pokrywają?
Na przykład załóżmy, że mamy zakresy oznaczone zmiennymi DateTime od
StartDate1do
EndDate1
i
od
StartDate2do
EndDate2.
Nie znaleziono powiązanych wyników
Zaproszony:
Aby odpowiedzieć na pytania, Zaloguj się lub Zarejestruj się
25 odpowiedzi
Anonimowy użytkownik
Potwierdzenie od:
(PoczątekA & < = KoniecB) i (KoniecA & > = PoczątekB
)
Dowód
:
Niech Warunek A oznacza DateRange A całkowicie po DateRange B.
(Prawda, jeśli )
Niech Warunek B oznacza DateRange A całkowicie poprzedza DateRange B
(Prawda, jeśli )
Wtedy zachodzi na siebie nakładanie się, jeśli ani A, ani B nie są prawdziwe -
(Jeśli jeden zakres nie występuje całkowicie po drugim,
nie całkowicie przed innym,
wtedy powinny się pokrywać.)
Więc tutaj jest jeden z
prawa de Morgana
https://en.wikipedia.org/wiki/De_Morgan%27s_laws
stwierdza, że:
<=> Co tłumaczy się jako: UWAGA: Obejmuje to warunki, w których krawędzie dokładnie zachodzą na siebie. Jeśli chcesz to wykluczyć,
zmień instrukcje na i na Uwaga 2: Dzięki @Baodad, zobacz
ten blog
http://baodad.blogspot.com/201 ... .html
faktyczne nakładanie się jest najmniejsze:
{ , , , }
Uwaga 3. Dzięki @tomosius, krótsza wersja brzmi:
W rzeczywistości jest to skrót składniowy do dłuższej implementacji, która obejmuje dodatkowe kontrole, aby upewnić się, że daty rozpoczęcia przypadają na lub przed datami końcowymi. Wyprowadzamy to z góry:
Jeśli daty rozpoczęcia i zakończenia mogą być poza kolejnością, tj. Jeśli jest możliwe, że lub , powinieneś również sprawdzić, czy są w porządku, oznacza to, że musisz dodać dwie dodatkowe reguły akcji:
lub:
lub,
lub:
Ale żeby zaimplementować i , musisz napisać jakiś kod (używając potrójnego kodu C dla zwięzłości):
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
biblioteka okresów dla .NET
http://www.codeproject.com/KB/ ... .aspx
opisuje zależność między dwoma okresami czasu, wymieniając
PeriodRelation
:
Anonimowy użytkownik
Potwierdzenie od:
interwał algebra Allena
http://en.wikipedia.org/wiki/A ... ra... Opisuje 13 możliwych relacji, które mogą mieć dwa interwały względem siebie. Możesz znaleźć inne linki - „Allen Interval” wydaje się być operacyjnym hasłem wyszukiwania. Możesz również znaleźć informacje o tych operacjach
w rozwoju aplikacji zorientowanych czasowo w języku SQL Snodgrass (
http://www.cs.arizona.edu/~rts/publications.html
PDF dostępny online pod adresem URL), a także w Date, Darwen i Lorentzos
Temporary Data and the Relational Model
https://rads.stackoverflow.com ... Y0W0E
(2002) lub
Time and Relational Theory: Temporary Databases in the Relational Model and SQL
https://rads.stackoverflow.com ... SNSUG
(2014; właściwie druga edycja TD & RM).
Krótka (ish) odpowiedź: podane dwa zakresy dat i ze składnikami i oraz ograniczenie , to te dwa przedziały nakładają się, jeśli:
Możesz dostosować za pomocą kontra i versus jako zgodnie z wymaganiami do stopnia nakładania się.
ErikE komentuje:
Możesz uzyskać tylko 13, jeśli uważasz, że rzeczy są zabawne ... Mogę uzyskać 15 możliwych relacji, które mogą mieć dwa interwały, kiedy oszaleję. Przy rozsądnej liczbie dostaję tylko sześć, a jeśli odrzucisz obawę, że A lub B jest pierwsze, otrzymam tylko trzy (bez nakładania się, częściowo zachodzenia, jeden całkowicie wewnątrz drugiego). 15 brzmi tak: [38, początek, wnętrze, koniec, po], [39, wnętrze, koniec, po], [40, koniec, po], [41, po], [42].
Myślę, że nie można policzyć dwóch wpisów „przed: przed” i „po: po”. Mogłem zobaczyć 7 wpisów, jeśli zrównasz niektóre relacje z ich inwersjami (zobacz diagram w odnośniku URL Wikipedii; zawiera 7 wpisów, z których 6 ma różne opinie, a równe sobie nie mają wyraźnych opinii). To, czy trzy są rozsądne, zależy od twoich wymagań.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
po prostu upewniając się, że określony zakres zaczyna się wcześniej!
Zapewniasz, że pierwszy zakres rozpocznie się wcześniej (lub w tym samym czasie), zmieniając zakresy z wyprzedzeniem, jeśli to konieczne.
Następnie możesz wykryć nakładanie się, jeśli drugi początek zakresu jest mniejszy lub równy końcowi pierwszego zakresu (jeśli zakresy obejmują zarówno czas rozpoczęcia, jak i zakończenia) lub mniej (jeśli zakresy obejmują początek i wykluczają koniec).
Zakładając inkluzywność na obu końcach, istnieją tylko cztery możliwości, z których jedna się nie pokrywa:
Punkt końcowy zakresu 2 nie jest w nim zawarty. A więc w pseudokodzie:
Można to jeszcze bardziej uprościć:
Jeśli zakresy są włączone na początku i wyłączne na końcu, wystarczy zamienić na w drugim (w przypadku kodu pierwszego segmentu: w drugim segmencie należy użyć , a nie ):
Znacząco ograniczasz liczbę sprawdzeń, które musisz wykonać, ponieważ wcześnie usuwasz połowę problemu, zapewniając, że zakres 1 nigdy nie rozpocznie się po zakresie 2.
Anonimowy użytkownik
Potwierdzenie od:
Testy są oparte na liczbach całkowitych, ale ponieważ obiekty daty JavaScript są porównywalne, możesz po prostu dodać dwa obiekty daty. Możesz też dodać milisekundowy znacznik czasu.
Kod:
>
<pre class="lang-javascript prettyprint-override">
Testy:
>
<pre class="lang-javascript prettyprint-override">
Wynik po uruchomieniu z karmą, jaśminem i PhantomJS:
PhantomJS 1.9.8 (Linux): ukończono 20 z 20 SUKCESÓW (0,003 s/0,004 s)
Anonimowy użytkownik
Potwierdzenie od:
Java
który również działa w nieograniczonych odstępach czasu
<pre class="lang-java prettyprint-override">
Anonimowy użytkownik
Potwierdzenie od:
Oto kod, który robi magię:
Gdzie..
Dowód? Sprawdź ten test
treść kodu konsoli
https://gist.github.com/sandee ... a0b61
.
Anonimowy użytkownik
Potwierdzenie od:
Gdzie jest czymś w rodzaju
Anonimowy użytkownik
Potwierdzenie od:
----------------------|-------A-------|----------------------
|----B1----|
|----B2----|
|----B3----|
|----------B4----------|
|----------------B5----------------|
|----B6----|
----------------------|-------A-------|----------------------
|------B7-------|
|----------B8-----------|
|----B9----|
|----B10-----|
|--------B11--------|
|----B12----|
|----B13----|
----------------------|-------A-------|----------------------
moim rozwiązaniem roboczym był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.)
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
momentjs
:
odpowiedź opiera się na powyższych odpowiedziach, ale jest skrócona.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
doskonała odpowiedź
https://stackoverflow.com/a/325964/2314737
@charles-bretana.
Jednak odpowiedź nie rozróżnia przedziałów otwartych, zamkniętych i półotwartych (lub półotwartych).
Przypadek 1
: A, B - zamknięte przedziały
Nakładające się iff:
Przypadek 2
: A, B-otwarte przedziały
Nakładające się iff:
Przypadek 3
: A, B otwarte w prawo
Warunek nakładania się:
Przypadek 4
: A, B pozostawione otwarte
Warunek nakładania się:
Przypadek 5
: otwieranie z prawej, zamykanie B
Warunek nakładania się:
itp.
..
Wreszcie, ogólny warunek nakładania się dwóch przedziałów to
(StartA & < EndB) i (EndA & > StartB
)
gdzie zamienia ścisłą nierówność w nieścisłą nierówność za każdym razem, gdy dokonuje się porównania między dwoma uwzględnionymi punktami końcowymi.
Anonimowy użytkownik
Potwierdzenie od:
Najłatwiejszym sposobem jest użycie dobrze zaprojektowanej biblioteki niestandardowej do pracy z datami i godzinami.
<pre class="lang-java prettyprint-override">
java.time & amp; ThreeTen - opcjonalnie
>
Najlepsze w biznesie są ramy https://docs.oracle.com/javase ... .html
zbudowany w Javie 8 i nowszych. Dodaj do tego projektu
ThreeTen-Extra
http://www.threeten.org/threeten-extra/
który rozszerza java.time o dodatkowe klasy, a mianowicie klasę http://www.threeten.org/threet ... .html
których potrzebujemy tutaj.
Jeśli chodzi o tag w tym pytaniu, kod źródłowy obu projektów jest dostępny do użytku w innych językach (zwróć uwagę na ich licencje).
>
Klasa http://www.threeten.org/threet ... .html
przydatne, ale wymaga momentów czasu i daty (obiekty ), a nie tylko wartości daty. Dlatego nadal używamy pierwszej chwili dnia UTC do reprezentowania daty.
<pre class="lang-java prettyprint-override">
Utwórz , aby przedstawić ten przedział czasu.
<pre class="lang-java prettyprint-override">
Możemy również zdefiniować z punktem początkowym plus http://docs.oracle.com/javase/ ... .html
.
<pre class="lang-java prettyprint-override">
Porównanie z testem nakładania się jest łatwe.
<pre class="lang-java prettyprint-override">
Możesz porównać http://www.threeten.org/threet ... .html
z innym http://www.threeten.org/threet ... .html
lub http://docs.oracle.com/javase/ ... Dtrue
:
Wszyscy używają metody do określenia przedziału czasu, w którym następuje początek
włącznie
a koniec jest
Ekskluzywny
.
Anonimowy użytkownik
Potwierdzenie od:
endDate = '0000-00-00' nie możesz użyć BETWEEN, ponieważ 0000-00-00 nie jest prawidłową datą!
Użyłem tego rozwiązania:
Jeśli data początkowa2 jest wyższa, daty końcowe nie pokrywają się!
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
W stanie zamkniętym lub otwartym granic przedziałów czasowych rozwiązanie problemu @ Bretany jest dopuszczalne
na zamknięte okresy
(PoczątekA & < = KoniecB) i (KoniecA & > = PoczątekB)
można przepisać
na półotwarte przerwy
do:
(PoczątekA & < KoniecB) i (KoniecA & > PoczątekB)
Ta korekta jest konieczna, ponieważ otwarta granica przedziału z definicji nie jest częścią zakresu wartości przedziału.
Jeśli chodzi o
puste miejsca
, to tutaj związek pokazany powyżej nie zachowuje się jak NIE. Puste przedziały, które z definicji nie zawierają żadnej prawidłowej wartości, należy traktować jako przypadek specjalny. Demonstruję to w mojej bibliotece czasu Java
Time4J
https://github.com/MenoData/Time4J
w tym przykładzie:
Przedni nawias kwadratowy „[” oznacza zamknięty początek, a ostatni nawias „)” oznacza otwarty koniec.
Jak pokazano powyżej, puste przęsła naruszają powyższy warunek nakładania się (zwłaszcza startA & < endB), więc Time4J (i inne biblioteki) musi traktować to jako specjalny przypadek krawędzi, aby upewnić się, że dowolne odstępy nie nakładają się na puste odstępy. Oczywiście przedziały dat (które są domyślnie zamknięte w Time4J, ale mogą być półotwarte lub puste) są obsługiwane w podobny sposób.
Anonimowy użytkownik
Potwierdzenie od:
Dzieje się tak, oczywiście, jeśli rozważasz odstępy czasu, w których StartDate jest zawsze przed EndDate.
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
Anonimowy użytkownik
Potwierdzenie od:
https://i.stack.imgur.com/qzRBx.png
(Zielony to bieżący interwał, niebieskie bloki to interwały, czerwone to nakładające się interwały).
Dopasowałem odpowiedź Iana Nelsona do następującego rozwiązania:
To pasuje do wszystkich przypadków pokrywania się, ale ignoruje dozwolone przypadki nakładania się.