Tengo dos intervalos de fechas donde cada rango está determinado por una fecha de inicio y finalización (obviamente, instancias datetime.date()). Los dos rangos pueden superponerse o no. Necesito el número de días de la superposición. Por supuesto, puedo precompletar dos conjuntos con todas las fechas dentro de ambos rangos y realizar una intersección establecida, pero esto posiblemente sea ineficiente ... ¿hay una mejor manera aparte de otra solución que utiliza una sección larga if-elif que cubra todos los casos?¿Cálculo de superposición de rango de fechas eficiente en python?
Respuesta
- Determine la última de las dos fechas de inicio y la primera de las dos fechas de finalización.
- Calcula el timedelta restándolo.
- Si el delta es positivo, ese es el número de días de superposición.
Aquí es un ejemplo de cálculo:
>>> from datetime import datetime
>>> from collections import namedtuple
>>> Range = namedtuple('Range', ['start', 'end'])
>>> r1 = Range(start=datetime(2012, 1, 15), end=datetime(2012, 5, 10))
>>> r2 = Range(start=datetime(2012, 3, 20), end=datetime(2012, 9, 15))
>>> latest_start = max(r1.start, r2.start)
>>> earliest_end = min(r1.end, r2.end)
>>> delta = (earliest_end - latest_start).days + 1
>>> overlap = max(0, delta)
>>> overlap
52
Pseudocódigo:
1 + max(-1, min(a.dateEnd, b.dateEnd) - max(a.dateStart, b.dateStart))
llamadas a funciones son más caras que las operaciones aritméticas.
La forma más rápida de hacer esto implica 2 sustracciones y 1 min():
min(r1.end - r2.start, r2.end - r1.start).days + 1
en comparación con la siguiente mejor que necesita 1 resta, 1 min() y un máximo():
(min(r1.end, r2.end) - max(r1.start, r2.start)).days + 1
Por supuesto, con ambas expresiones, aún necesita verificar si hay una superposición positiva.
Este método no devolverá la respuesta correcta siempre. p.ej.'Range = namedtuple ('Range', ['start', 'end']) r1 = Rango (start = datetime (2016, 6, 15), end = datetime (2016, 6, 15)) r2 = Rango (start = datetime (2016, 6, 11), end = datetime (2016, 6, 18)) print min (r1.end - r2.start, r2.end - r1.start) .days + 1' se imprimirá 4 donde supuso imprimir 1 – tkyass
def get_overlap(r1,r2):
latest_start=max(r1[0],r2[0])
earliest_end=min(r1[1],r2[1])
delta=(earliest_end-latest_start).days
if delta>0:
return delta+1
else:
return 0
Implementé una clase TimeRange como se puede ver a continuación.
El get_overlapped_range primero niega todas las opciones no superpuestas por una condición simple, y luego calcula el rango superpuesto considerando todas las opciones posibles.
para obtener la cantidad de días que tendrá que tomar el valor que fue devuelto TimeRange de get_overlapped_range y dividir la duración de 60 * 60 * 24 (:
TimeRange clase (objeto):
def __init__(self, start, end):
self.start = start
self.end = end
self.duration = self.end - self.start
def is_overlapped(self, time_range):
if max(self.start, time_range.start) < min(self.end, time_range.end):
return True
else:
return False
def get_overlapped_range(self, time_range):
if not self.is_overlapped(time_range):
return
if time_range.start >= self.start:
if self.end >= time_range.end:
return TimeRange(time_range.start, time_range.end)
else:
return TimeRange(time_range.start, self.end)
elif time_range.start < self.start:
if time_range.end >= self.end:
return TimeRange(self.start, self.end)
else:
return TimeRange(self.start, time_range.end)
def __repr__(self):
return '{0} ------> {1}'.format(*[time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(d))
for d in [self.start, self.end]])
Ya existe una solución perfecta para el problema de OP. –
- 1. Fecha Rango Superposición con anulable Fechas
- 2. Generador de rango de fechas de Python durante días hábiles
- 3. Comparación de rango de fecha múltiple para superposición: ¿cómo hacerlo de manera eficiente?
- 4. oráculo rango de fechas
- 5. jQuery Validate (Rango de fechas)
- 6. Crear un rango de fechas
- 7. SQL Rango de fechas dividido
- 8. selector de rango de fechas similar al selector de rango de fechas de Google Analytics?
- 9. Grupo MySQL por intervalos en un rango de fechas
- 10. Rango de fechas en una matriz, ruby
- 11. Epopoximación eficiente de bajo rango en MATLAB
- 12. Cálculo del rango por percentil
- 13. Crear rango de fechas de mysql
- 14. determinar si el rango de fechas se encuentra entre otro rango de fechas - sql
- 15. Comprobar superposición de los intervalos de fechas en MySQL
- 16. Cálculo del rango percentil en MySQL
- 17. Cálculo de fechas relativas usando asp.net mvc
- 18. Cálculo de la fecha hebrea en Python
- 19. algoritmo reto: rango de fechas fusión
- 20. Java: Rango de fechas mín. Y máx.
- 21. C++ Cálculo eficiente de una media móvil
- 22. Comprobación de conflictos de rango de fechas en MySQL
- 23. ¿Cómo determinar si un rango de fechas ocurre en cualquier momento dentro de otro rango de fechas?
- 24. deshabilitar el rango de fechas en el calendario de Joomla
- 25. Grupo por rango de fechas en semanas/meses de intervalo
- 26. Generación de un informe por rango de fechas en raíles
- 27. más eficiente Cálculo coseno R
- 28. Generación de todas las fechas dentro de un rango determinado en Python
- 29. Cómo iterar en un rango de fechas en PL/SQL
- 30. Obteniendo la lista de fechas en un rango en PostgreSQL
Excelente respuesta –
+1 para crear la tupla llamada 'Rango '. :-) – GaretJax
+1 para código elegante. Acabo de tomar esta rutina y la utilicé en mi aplicación PHP. – Eric