2010-07-07 36 views
5

estoy buscando una respuesta ampliada a la pregunta formulada aquí:Fecha Rango Superposición con anulable Fechas

Determine Whether Two Date Ranges Overlap

en cualquiera de las fechas, ya sea en el intervalo de fechas puede ser nulo. He encontrado la siguiente solución, pero no estoy seguro si se puede simplificar aún más.

(StartA == NULL || StartA <= EndB) && 
(EndA == NULL || EndA >= StartB) && 
(StartB == NULL || StartB <= EndA) && 
(EndB == NULL || EndB >= StartA) 

Suponiendo:

rangos DateTime de starta a EndA y StartB a ENDB

EDIT: En este momento me tiró rápidamente la lógica anterior juntos, lo que parece fallar cuando cualquiera de inicio y final del rango las fechas son NULL. Vea la solución de David a continuación para un mejor enfoque bien explicado de &.

+0

tendrá un error si StartA es nulo, porque el operador de comparación no funciona con nulo. Convierta todo o Gate {Logic} en {Logic} y luego reorganice las declaraciones poniendo all compare in null al inicio para que el cortocircuito y {Logic} funcionen. –

Respuesta

12

Este caso puede ser manejado por una ligera generalización de Charles Bretana's excellent answer a esa pregunta.

Deje CONDA Mean DateRange Un completo después de DateRange B (Verdadero si starta> ENDB) Deje CondB Mean DateRange Un completamente antes de DateRange B (Verdadero si EndA < StartB)

En este caso, en el supuesto desea una fecha nula para representar "sin límite inicial/final", las condiciones se modifican.Para CondA, por ejemplo, para que DateRange A esté completamente después del DateBange B, DateRange A debe tener un tiempo de inicio definido, DateRange B debe tener un tiempo de finalización definido, y el tiempo de inicio de A debe ser posterior al tiempo de finalización de B:

CondA := (StartA != null) && (EndB != null) && (StartA > EndB) 

CondB es el mismo con A y B conmuta:

CondB := (StartB != null) && (EndA != null) && (StartB > EndA) 

Continua,

Entonces existe superposición si ni A ni B es cierto

Overlap := !(CondA || CondB) 

y

Ahora la ley de De Morgan, creo que es, cuenta que

No (A o B) < = > Not A y B no

Overlap == !CondA && !CondB 
     == ![(StartA != null) && (EndB != null) && (StartA > EndB)] && 
      ![(StartB != null) && (EndA != null) && (StartB > EndA)] 
     == [(StartA == null) || (EndB == null) || (StartA <= EndB)] && 
      [(StartB == null) || (EndA == null) || (StartB <= EndA)] 

Creo que esto es en realidad un poco más robusto que la solución que desarrolló, porque si EndB == NULL pero StartA no es nulo, su primera condición terminará comparando StartA <= NULL. En la mayoría de los idiomas con los que estoy familiarizado, es una condición de error.

+0

¡Gracias por la explicación detallada, David! Sí, me di cuenta de que mi solución inicial se desmorona rápidamente después de publicarla. – Josh

+0

Enfoque agradable como la ley deMorgan, pero no puede implementar la segunda parte como enunciado de programación, porque si cualquiera de startA o EndB como ejemplo son nulos, el operador de comparación fallará. Trate de mantener solo el operador And {&&}, ya que funcionará como un cortocircuito en la mayoría de los nuevos compiladores. Esto es correcto como bajo y como programación. ! [(StartA! = Null) && (EndB! = Null) && (StartA> EndB)] && ! [(StartB! = Null) && (EndA! = Null) && (StartB> EndA)] –

+1

@Waleed : Si estás hablando de mis dos últimas líneas de código, eso ciertamente puede implementarse como una declaración. Si 'startA' o' endB' es igual a 'null', eso quedará atrapado por las pruebas explícitas para esa condición y nunca se realizará la comparación' <= '. '||' también usa la evaluación de cortocircuito. (La mayoría de los compiladores probablemente optimizarían usando la ley de DeMorgan para que las últimas dos líneas y las dos líneas anteriores generen el mismo código compilado). –

0

Eso es probablemente tan simple como se puede obtener, aunque en realidad no lo he probado.

Es probable que no vale la pena para simplificar aún más, ya que el bloque termina siendo aproximadamente 8 operaciones en el peor de los casos (4, en promedio, gracias a la evaluación de cortocircuito).

0

Todas las respuestas se basan si la condición es verdadera. Me gustaría agregar una nota aquí.

1- La DateTime tipo de variable es una estructura y no se puede establecer en nulo a menos que esté utilizando un tipo que admite nulos como "DateTime?"

2- para encontrar el rango de superposición siga los pasos siguientes

DateTime? StartOverLap = null,EndOverLap = null; 
      if (StartA != null && StartB != null) 
      { 
       StartOverLap = StartA > StartB ? StartA : StartB; 
      } 
      else if (StartA == null && StartB != null) 
      { 
       StartOverLap = StartB; 
      } 
      else if (StartA != null && StartB == null) 
      { 
       StartOverLap = StartA; 
      } 
      if (EndA != null && EndB != null) 
      { 
       EndOverLap = EndA < EndB ? EndA : EndB; 
      } 
      else if (EndA == null && EndB != null) 
      { 
       EndOverLap = EndB; 
      } 
      else if (EndA != null && EndB == null) 
      { 
       EndOverLap = EndA; 
      } 
      if (StartOverLap != null && EndOverLap == null) 
      { 
       if (EndOverLap < StartOverLap) 
       { 
        StartOverLap = null; 
        EndOverLap = null; 
       } 
      } 
0

Sin considerar nulos, respuesta es

(StartA <= EndB) and (EndA >= StartB) (ver this para una explicación detallada)

considerando nulos de inicio y fechas de finalización,
utilizando la sintaxis del operador terciario C:
(StartA != null? StartA: EndB <= EndB != null? EndB: StartA) && (EndA != null? EndA: StartB >= StartB != null? StartB: EndA)

o C# 4.x estilo operadores nulos:

(StartA??EndB <= EndB??StartA) && (EndA??StartB >= StartB??EndA)

o en SQL:

(Coalesce(StartA, EndB) <= Coalesce(EndB, StartA)) And (Coalesce(EndA, StartB) <= Coalesce(StartB , EndA))

Explicación:
considerar que la respuesta no es nulo:
(StartA <= EndB) and (EndA >= StartB)

Ahora, considere que StartA es nulo, lo que indica que el rango de fechas A existe desde el comienzo del tiempo (BOT).En ese caso, DateRangeB nunca puede estar antes de DateRangeA. Así que la primera condición, (StartA (BOT) < = EndB) SIEMPRE será verdadera, sin importar qué EndB sea. Así que cambie esta expresión para que en lugar de comparar null con EndB, cuando StartA es nulo, compare EndB consigo mismo No importa qué EndB sea, la expresión EndB <= EndB será verdadera. (Podríamos crear variables para representar BOT y EOT, pero esto es más fácil).

Haga lo mismo con otras tres variables de entrada.

Cuestiones relacionadas