我有一个从不同日期获得的datetime.time()
范围的列表,按init
排序,我需要获得考虑重叠时间的输出。例如,
[{'init': datetime.time(10,0,0), 'end': datetime.time(12,0,0)},
{'init': datetime.time(11,0,0), 'end': datetime.time(12,30,0)},
{'init': datetime.time(22,0,0), 'end': datetime.time(4,30,0)},
{'init': datetime.time(23,0,0), 'end': datetime.time(0,30,0)}]
输出应为:
[{{'init': datetime.time(10,0,0), 'end': datetime.time(12,30,0)},
{'init': datetime.time(22,0,0), 'end': datetime.time(4,30,0)}
为此,我将遍历列表中的每个项目,并根据是否满足条件(即该项目与上一个项目完全或部分重叠)来更新init和end值。
x, y = range_list[0]['init'], range_list[0]['end']
for range in range_list:
if range['init'] <= y:
if range['end'] > y:
y = range['end']
else:
print(x, y)
x = range['init']
y = range['end']
但是,按照这种逻辑,我不能使用隔夜范围,因为例如22:00:00
不小于04:30:00
。
在控制输入数据时,我想返回带有完整datetime
对象或timestamp
对象的列表,例如
[{'init': datetime.time(2019,1,12,10,0,0), 'end': datetime.time(2019,1,12,12,0,0)},
{'init': datetime.time(2019,1,13,11,0,0), 'end': datetime.time(2019,1,13,12,30,0)},
{'init': datetime.time(2019,1,14,22,0,0), 'end': datetime.time(2019,1,15,4,30,0)},
{'init': datetime.time(2019,1,16,23,0,0), 'end': datetime.time(2019,1,17,0,30,0)}]
但是,这将不起作用,因为由于日期的原因,每个项目都将高于上一个。
那么,我该如何解决这个问题?
TL; DR;如果无法使用完整的datetime
或timestamp
,如何在一夜之间处理时间范围?
答案 0 :(得分:0)
我改变了主意(和答案),现在认为您应该定义自己的数据结构以保存字典中的时间。这样,您就可以轻松地将结束时间调整为相对于开始时间的同一天。
在range_list下面的代码中,它具有与您的问题所示相同的值,因此可以根据需要更改结束时间来进行调整。
调整后,range_list
包含:
[{'init': Timestamp(10, 0, 0), 'end': Timestamp(12, 0, 0)}
{'init': Timestamp(11, 0, 0), 'end': Timestamp(12,30, 0)}
{'init': Timestamp(22, 0, 0), 'end': Timestamp(28,30, 0)}
{'init': Timestamp(23, 0, 0), 'end': Timestamp(24,30, 0)}]
由于您可以控制输入数据,因此最好以所需的格式创建它们。
from collections import namedtuple
from pprint import pprint, pformat
class Timestamp(namedtuple('Timestamp', 'h,m,s')):
def __repr__(self):
classname = self.__class__.__name__
return '{}({:2},{:2},{:2})'.format(classname, self.h, self.m, self.s)
range_list = [{'init': Timestamp(10,0,0), 'end': Timestamp(12,0,0)},
{'init': Timestamp(11,0,0), 'end': Timestamp(12,30,0)},
{'init': Timestamp(22,0,0), 'end': Timestamp(4,30,0)},
{'init': Timestamp(23,0,0), 'end': Timestamp(0,30,0)}]
# Adjust end times.
for i, interval in enumerate(range_list):
init, end = interval['init'], interval['end']
range_list[i] = {'init': init,
'end' : Timestamp(end.h+24 if end.h < init.h else end.h,
end.m, end.s)}
def merge(intervals):
merged = []
x, y = intervals[0]['init'], intervals[0]['end']
for interval in intervals:
if interval['init'] <= y:
if interval['end'] > y:
y = interval['end']
else:
merged.append({'init': x, 'end': y})
x = interval['init']
y = interval['end']
merged.append({'init': x, 'end': y})
return merged
print(merge(range_list))
输出:
[{'init': Timestamp(10, 0, 0), 'end': Timestamp(12,30, 0)},
{'init': Timestamp(22, 0, 0), 'end': Timestamp(28,30, 0)}]
答案 1 :(得分:0)
我实际上是使用datetime
来解决此问题的,但在固定的日期。
给出如下输入数据:
ranges = [{'init': datetime.time(10,0,0), 'end': datetime.time(12,0,0)},
{'init': datetime.time(11,0,0), 'end': datetime.time(12,30,0)},
{'init': datetime.time(22,0,0), 'end': datetime.time(4,30,0)},
{'init': datetime.time(23,0,0), 'end': datetime.time(0,30,0)}]
我遍历每个项目,将它们转换为日期部分为datetime
的完整1970-01-01
对象。如果init
大于end
,我将向end
添加一天,仅此而已。现在,我可以处理夜间时间范围,而不会出现任何问题。
for range in ranges:
range['init'] = datetime.combine(datetime(1970, 1, 1), range['init'])
range['end'] = datetime.combine(datetime(1970, 1, 1), range['end'])
if range['init'] > range['end']:
range['end'] = range['end'].replace(day=2)
@martineau的答案未解决问题的要点。拥有更简洁的代码会有所帮助,但无法解决无法解决datetime
的夜间时间范围问题(最终成为问题,但不是真正的问题)