隔夜处理日期时间

时间:2019-01-16 11:59:20

标签: python python-3.x

我有一个从不同日期获得的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;如果无法使用完整的datetimetimestamp,如何在一夜之间处理时间范围?

2 个答案:

答案 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的夜间时间范围问题(最终成为问题,但不是真正的问题)