2
I am trying to calculate the total time in a list of date ranges in Python, and if there is intersection between the intervals, it must merge to be calculated as if it were a new interval.
Interval 1:
intervalos = [
{'inicio': datetime(2014, 11, 26, 10, 0, 0), 'fim': datetime(2014, 11, 26, 12, 0, 0)},
{'inicio': datetime(2014, 11, 26, 11, 0, 0), 'fim': datetime(2014, 11, 26, 13, 0, 0)},
]
self.assertEqual(calcular_tempo(intervalos), 10800)
Interval 2:
intervalos = [
{'inicio': datetime(2014, 11, 26, 10, 0, 0), 'fim': datetime(2014, 11, 26, 11, 0, 0)},
{'inicio': datetime(2014, 11, 26, 10, 30, 0), 'fim': datetime(2014, 11, 26, 11, 30, 0)},
{'inicio': datetime(2014, 11, 26, 12, 0, 0), 'fim': datetime(2014, 11, 26, 12, 30, 0)},
{'inicio': datetime(2014, 11, 26, 9, 0, 0), 'fim': datetime(2014, 11, 26, 13, 0, 0)},
]
self.assertEqual(calcular_tempo(intervalos), 14400)
Interval 3:
intervalos = [
{'inicio': datetime(2014, 11, 26, 10, 0, 0), 'fim': datetime(2014, 11, 26, 11, 0, 0)},
{'inicio': datetime(2014, 11, 26, 10, 30, 0), 'fim': datetime(2014, 11, 26, 11, 30, 0)},
{'inicio': datetime(2014, 11, 26, 12, 0, 0), 'fim': datetime(2014, 11, 26, 12, 30, 0)},
{'inicio': datetime(2014, 11, 26, 12, 40, 0), 'fim': datetime(2014, 11, 26, 12, 50, 0)},
{'inicio': datetime(2014, 11, 26, 5, 0, 0), 'fim': datetime(2014, 11, 26, 10, 1, 0)},
]
self.assertEqual(calcular_tempo(intervalos), 25860)
I created a method to perform the calculation, however the result is failing for some tests the code works but the logic is weak.
The method:
def calcular_tempo(objetos):
intervalos = []
intervalos_add = []
intervalos_del = []
for objeto in objetos:
if intervalos:
for intervalo in intervalos:
if intervalo['inicio'] < objeto['inicio'] < intervalo['fim']:
if objeto['fim'] > intervalo['fim']:
intervalos_del.append(intervalo)
intervalos_add.append({'inicio': intervalo['inicio'], 'fim': objeto['fim']})
elif intervalo['fim'] > objeto['fim'] > intervalo['inicio']:
if objeto['inicio'] < intervalo['inicio']:
intervalos_del.append(intervalo)
intervalos_add.append({'inicio': objeto['inicio'], 'fim': intervalo['fim']})
elif objeto['inicio'] < intervalo['inicio'] and objeto['fim'] > intervalo['fim']:
intervalos_del.append(intervalo)
intervalos_add.append(objeto)
elif objeto['inicio'] != intervalo['inicio'] and objeto['fim'] != intervalo['fim']:
intervalos_add.append(objeto)
else:
intervalos.append(objeto)
for deletar in intervalos_del:
intervalos.remove(deletar)
intervalos_sem_repeticoes = []
for add in intervalos_add:
if add not in intervalos_sem_repeticoes:
intervalos_sem_repeticoes.append(add)
intervalos = intervalos + intervalos_sem_repeticoes
intervalos_add = []
intervalos_del = []
segundos_totais = 0
for intervalo in intervalos:
segundos_totais += (intervalo['fim'] - intervalo['inicio']).total_seconds()
return segundos_totais
I believe that I am redundant in logic and leaving something to be desired in checking the intervals. I wasn’t going to put the method I did not influence, it would be interesting if they did this logic from scratch, because it must be simpler than the algorithm I did.
I just found out my code was working. However this your code worked perfectly, which comes to be annoying by the time you took to do this, kkk.
– Paulo