Angenommen, wir haben Bereiche, die durch DateTime-Variablen StartDate1
bis EndDate1
und StartDate2
bis EndDate2
bezeichnet sind.
Antworten
Zu viele Anzeigen?Dies war meine JavaScript-Lösung mit moment.js:
// Aktuelle Reihendaten
var dateStart = moment("2014-08-01", "YYYY-MM-DD");
var dateEnd = moment("2014-08-30", "YYYY-MM-DD");
// Überprüfung mit den obigen Daten
var rangeUsedStart = moment("2014-08-02", "YYYY-MM-DD");
var rangeUsedEnd = moment("2014-08-015", "YYYY-MM-DD");
// Deckt der Bereich andere ab?
if((dateStart <= rangeUsedStart) && (rangeUsedEnd <= dateEnd)) {
return false;
}
// Der Bereich überschneidet sich mit dem Start?
if((dateStart <= rangeUsedStart) && (rangeUsedStart <= dateEnd)) {
return false;
}
// Der Bereich überschneidet sich mit dem Ende?
if((dateStart <= rangeUsedEnd) && (rangeUsedEnd <= dateEnd)) {
return false;
}
// Alles gut
return true;
In Microsoft SQL SERVER - SQL Funktion
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) -- berücksichtigt innere und äußere Enddaten
OR
(@endDate1 BETWEEN @startDate2 AND @endDate2) -- berücksichtigt innere und äußere Startdaten
OR
(@startDate2 BETWEEN @startDate1 AND @endDate1) -- nur für äußeren Bereich erforderlich, in dem die Daten enthalten sind.
) THEN 1 ELSE 0 END
)
RETURN @Overlap
END
GO
-- Ausführung des obigen Codes
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
Die mathematische Lösung von @Bretana ist gut, vernachlässigt jedoch zwei spezifische Details:
- Aspekt geschlossener oder halboffener Intervalle
- leere Intervalle
Zur Frage, ob Intervallgrenzen geschlossen oder offen sind, ist die Lösung von @Bretana gültig für geschlossene Intervalle
(StartA <= EndB) und (EndA >= StartB)
kann für halboffene Intervalle umgeschrieben werden zu:
(StartA < EndB) und (EndA > StartB)
Diese Korrektur ist notwendig, da eine offene Intervallgrenze gemäß Definition nicht zum Wertebereich eines Intervalls gehört.
Und zu leeren Intervallen, nun, hier gilt die oben gezeigte Beziehung NICHT. Leere Intervalle, die per Definition keinen gültigen Wert enthalten, müssen als spezieller Fall behandelt werden. Ich zeige dies anhand meiner Java-Zeitbibliothek Time4J anhand dieses Beispiels:
MomentInterval a = MomentInterval.between(Instant.now(), Instant.now().plusSeconds(2));
MomentInterval b = a.collapse(); // mache b aus a ein leeres Intervall
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)
Die führende eckige Klammer "[" zeigt einen geschlossenen Start an, während die letzte Klammer ")" ein offenes Ende anzeigt.
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 überschneidet b: " + a.intersects(b)); // a überschneidet b: false
Wie oben gezeigt, verletzen leere Intervalle die Überschneidungsbedingung oben (insbesondere startA < endB), daher muss Time4J (und auch andere Bibliotheken) dies als speziellen Grenzfall behandeln, um sicherzustellen, dass die Überlappung eines beliebigen Intervalls mit einem leeren Intervall nicht existiert. Natürlich werden Datumintervalle (die standardmäßig in Time4J geschlossen sind, aber auch halboffen sein können, wie leere Datumintervalle) ähnlich behandelt.
Ich hatte eine Situation, in der wir Daten anstelle von Datumszeiten hatten, und die Daten nur am Anfang/Ende überlappen konnten. Beispiel unten:
(Grün ist das aktuelle Intervall, blaue Blöcke sind gültige Intervalle, rote sind überlappende Intervalle).
Ich habe die Antwort von Ian Nelson zu folgender Lösung angepasst:
(startB <= startA && endB > startA)
|| (startB >= startA && startB < endA)
Dies trifft alle Überlappungsfälle, ignoriert aber die erlaubten Überlappungsfälle.
das einfachste
Der einfachste Weg ist es, eine gut konzipierte dedizierte Bibliothek für Datum-Zeit-Arbeiten zu verwenden.
someInterval.overlaps( anotherInterval )
java.time & ThreeTen-Extra
Das Beste in der Branche ist das java.time
-Framework, das in Java 8 und später eingebaut ist. Dazu kommt das ThreeTen-Extra-Projekt, das java.time mit zusätzlichen Klassen ergänzt, insbesondere mit der hier benötigten Interval
-Klasse.
Was das language-agnostic
-Tag bei dieser Frage betrifft, der Quellcode für beide Projekte steht zur Verwendung in anderen Sprachen zur Verfügung (beachten Sie deren Lizenzen).
Interval
Die org.threeten.extra.Interval
-Klasse ist praktisch, erfordert jedoch Datum-Zeit-Momente (java.time.Instant
-Objekte) anstelle von nur Datumswerten. Daher gehen wir vor, indem wir den ersten Moment des Tages in UTC zur Darstellung des Datums verwenden.
Instant start = Instant.parse( "2016-01-01T00:00:00Z" );
Instant stop = Instant.parse( "2016-02-01T00:00:00Z" );
Erstellen Sie ein Interval
, um diesen Zeitraum darzustellen.
Interval interval_A = Interval.of( start , stop );
Sie können auch ein Interval
mit einem Startmoment plus einer Duration
definieren.
Instant start_B = Instant.parse( "2016-01-03T00:00:00Z" );
Interval interval_B = Interval.of( start_B , Duration.of( 3 , ChronoUnit.DAYS ) );
Der Vergleich zur Überlappung ist einfach.
Boolean overlaps = interval_A.overlaps( interval_B );
Sie können ein Interval
gegen ein anderes Interval
oder Instant
vergleichen:
All diese verwenden den Ansatz des Halboffenen
zum Definieren eines Zeitraums, bei dem der Anfang inklusiv und das Ende exklusiv ist.
3 Stimmen
Äußerst ähnlich wie stackoverflow.com/questions/306316/…
1 Stimmen
@CharlesBretana Vielen Dank dafür, du hast Recht - das ist fast wie eine zweidimensionale Version meiner Frage!
2 Stimmen
Sehr ähnlich wie stackoverflow.com/questions/117962/…
2 Stimmen
Teile die Situation "Die beiden Datumsbereiche überschneiden sich" in Fälle (es gibt zwei) und teste dann jeweils für jeden Fall.
0 Stimmen
Ich weiß, dass dies als sprachunabhängig markiert wurde, aber für alle, die in Java implementieren: Erfinden Sie das Rad nicht neu und verwenden Sie Joda Time. joda-time.sourceforge.net/api-release/org/joda/time/base/…
0 Stimmen
Wenn Daten NULL-Werte (oder leer) sein können, wenn sie nicht festgelegt sind, gibt es diese Frage, die eine Erweiterung dieser ist.
0 Stimmen
Algorithmus zum Zusammenführen überlappender Intervalle kann einige Hinweise geben.
1 Stimmen
Hallo.. A: StartDate1, B: EndDate1, C: StartDate2, D: EndDate2. Wenn B < C oder A > D, dann nehmen wir an, dass sie sich nicht überschneiden.. Also können wir einfach mit "isintersects = not (B < C oder A > D)" testen, ob es sich überschneidet oder nicht.
0 Stimmen
Noch ein Intervallhilfsprogramm für .Net github.com/AlexeyBoiko/IntervalUtility (Ich bin der Autor)