Determinar si dos rangos de fechas se superponen

Resuelto Ian Nelson asked hace 15 años • 40 respuestas

Dados dos intervalos de fechas, ¿cuál es la forma más sencilla o eficaz de determinar si los dos intervalos de fechas se superponen?

Como ejemplo, supongamos que tenemos rangos indicados por variables DateTime StartDate1hasta EndDate1 y StartDate2 hasta EndDate2.

Ian Nelson avatar Nov 28 '08 21:11 Ian Nelson
Aceptado

(InicioA <= FinB) y (FinA >= InicioB)

Prueba:
Deje que ConditionA signifique que DateRange A está completamente después de DateRange B

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

(Verdadero si StartA > EndB)

Deje que ConditionB signifique que DateRange A es completamente anterior a DateRange B

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

(Verdadero si EndA < StartB)

Entonces, la superposición existe si ni A ni B son verdaderos
(si un rango no está completamente después del otro
ni completamente antes del otro, entonces deben superponerse).

Ahora bien, una de las leyes de De Morgan dice que:

Not (A Or B) <=> Not A And Not B

Lo que se traduce en:(StartA <= EndB) and (EndA >= StartB)


NOTA: Esto incluye condiciones en las que los bordes se superponen exactamente. Si desea excluir eso,
cambie los >=operadores a >y <= a<


NOTA 2. Gracias a @Baodad, mira este blog , la superposición real es menor de:
{ endA-startA,,, }endA - startBendB-startAendB - startB

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


NOTA 3. Gracias a @tomosius, una versión más corta dice:
DateRangesOverlap = max(start1, start2) < min(end1, end2)
Este es en realidad un atajo sintáctico para lo que es una implementación más larga, que incluye comprobaciones adicionales para verificar que las fechas de inicio sean iguales o anteriores a las fechas de finalización. Derivando esto desde arriba:

Si las fechas de inicio y finalización pueden estar desordenadas, es decir, si es posible que startA > endAo startB > endB, entonces también debes verificar que estén en orden, lo que significa que debes agregar dos reglas de validez adicionales:
(StartA <= EndB) and (StartB <= EndA) and (StartA <= EndA) and (StartB <= EndB) o:
(StartA <= EndB) and (StartA <= EndA) and (StartB <= EndA) and (StartB <= EndB) o,
(StartA <= Min(EndA, EndB) and (StartB <= Min(EndA, EndB)) o:
(Max(StartA, StartB) <= Min(EndA, EndB)

Pero para implementar Min()and Max(), debe codificar (usando C ternario para mayor concisión):
((StartA > StartB) ? StartA : StartB) <= ((EndA < EndB) ? EndA : EndB)

Charles Bretana avatar Nov 28 '2008 15:11 Charles Bretana

Creo que basta con decir que los dos rangos se superponen si:

(StartDate1 <= EndDate2) and (StartDate2 <= EndDate1)
Ian Nelson avatar Nov 28 '2008 14:11 Ian Nelson

Este artículo Biblioteca de períodos de tiempo para .NET describe la relación de dos períodos de tiempo mediante la enumeración PeriodRelation :

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

ingrese la descripción de la imagen aquí

 avatar Apr 08 '2011 22:04