Ho due intervalli di date in cui ogni intervallo è determinato da una data di inizio e di fine (ovviamente, istanze datetime.date()). Le due gamme possono sovrapporsi o meno. Ho bisogno del numero di giorni della sovrapposizione. Naturalmente posso precompilare due serie con tutte le date all'interno di entrambi gli intervalli e eseguire un'intersezione impostata, ma questo è probabilmente inefficiente ... c'è un modo migliore a parte un'altra soluzione che utilizza una lunga sezione if-elif che copre tutti i casi?Calcolo di sovrapposizione intervallo di date efficiente in python?
risposta
- Determinare l'ultima delle due date di inizio e la prima delle due date di fine.
- Calcolare il timedelta sottraendolo.
- Se il delta è positivo, è il numero di giorni di sovrapposizione.
Ecco un esempio di calcolo:
>>> 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
Pseudocodice:
1 + max(-1, min(a.dateEnd, b.dateEnd) - max(a.dateStart, b.dateStart))
chiamate di funzione sono più costosi di operazioni aritmetiche.
Il modo più veloce per farlo comporta 2 sottrazioni e 1 min():
min(r1.end - r2.start, r2.end - r1.start).days + 1
rispetto alla migliore seguente che ha bisogno di 1 sottrazione, 1 min() e un massimo():
(min(r1.end, r2.end) - max(r1.start, r2.start)).days + 1
Naturalmente con entrambe le espressioni è ancora necessario verificare una sovrapposizione positiva.
Questo metodo non restituirà sempre la risposta corretta. per esempio.'Range = namedtuple ('Range', ['start', 'end']) r1 = Intervallo (start = datetime (2016, 6, 15), end = datetime (2016, 6, 15)) r2 = Intervallo (start = datetime (2016, 6, 11), end = datetime (2016, 6, 18)) stampa min (r1.end - r2.start, r2.end - r1.start) .days + 1' stampa 4 dove suppose di stampare 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
Ho implementato una classe TimeRange come potete vedere di seguito.
L'oggetto get_overlapped_range prima nega tutte le opzioni non sovrapposte a una condizione semplice, quindi calcola l'intervallo sovrapposto considerando tutte le opzioni possibili.
per ottenere la quantità di giorni avrete bisogno di prendere il valore TimeRange che è stato restituito da get_overlapped_range e dividere la durata del 60 * 60 * 24 (:
classe TimeRange (oggetto):
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]])
Esiste già una soluzione perfetta per il problema dell'OP. –
- 1. elasticsearch intervallo di date intersezione
- 2. Intervallo di date JavaScript nell'intervallo di date
- 3. built in funzione per il calcolo della sovrapposizione in Python
- 4. Dividi intervallo di date in blocchi dell'intervallo di date
- 5. jQuery Validate (Intervallo di date)
- 6. Gruppo MySQL a intervalli in un intervallo di date
- 7. Intervallo di date in PL/SQL (Oracle)
- 8. Intervallo di date in un array, rubino
- 9. Intervallo di date limite in Joda Time
- 10. Filtra per intervallo di date in SPARQL
- 11. Campi intervallo di date univoci in SQL Server 2008
- 12. Date di calcolo in oracle sql
- 13. Calcolo della differenza di date In Postgresql
- 14. Intervallo di date eloquente di Laravel - Richiesta tra due date
- 15. Verificare se un intervallo di date è all'interno di un intervallo di date
- 16. efficiente calcolo di una potenza di 2
- 17. determinare se intervallo di date cade tra un altro intervallo di date - sql
- 18. Pandas Calcolo VWAP efficiente
- 19. intersezione intervallo data python
- 20. Problema di calcolo degli intervalli di date sovrapposti
- 21. Gruppo per intervallo di date settimane/mesi intervallo
- 22. Come interrogare Cassandra per intervallo di date
- 23. PostgreSQL- Filtra un intervallo di date
- 24. Convenzione URL per intervallo di date
- 25. interrogazione Firebase da intervallo di date
- 26. Come posso evitare la sovrapposizione di date in SQL?
- 27. Interrogazione per intervallo di date nei binari
- 28. Calcolo dei giorni al mese tra un intervallo di due date
- 29. elasticsearch intervallo di date arrivare ieri
- 30. ASP.Net MVC Convalida intervallo di date discreto
Risposta eccellente –
+1 per creare la tupla denominata 'Range'. :-) – GaretJax
+1 per codice elegante. Ho appena preso questa routine e l'ho usata nella mia app PHP. – Eric