从“每秒”列表中提取最新的日期时间

时间:2014-08-15 10:09:09

标签: python datetime

假设我有一个日期时间对象的排序列表times。我希望从该列表中提取另一个列表,该列表可能更长或更短,但是它将包括原始列表中的至少一些(如果不是全部)元素,但是一些可能以下列方式重复:

首先是虚拟"开始时间"将被设置,这是最新的舍入到秒的时间,不晚于原始列表中的任何日期时间。例如,如果原始列表是

dts = [datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
       datetime.datetime(2014, 8, 15, 13, 1, 42, 158749),
       datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
       datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
       datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]
然后"开始时间"将是

start_time = datetime.datetime(2014, 8, 15, 13, 1, 41)

然后,这" start_time"每次迭代进行一秒,每次这样的迭代产生原始列表中的最后一个日期时间,该日期时间不晚于当前的时间"。当所有原始日期时间早于当前时间时,它将暂停。例如,给定上面的原始列表,输出应该是

output = [datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
          datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
          datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
          datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
          datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]

您能想到一种简单(高效)的方法来实现这一目标吗?

1 个答案:

答案 0 :(得分:3)

使用bisect module在生成器函数中查找每个datetime对象。将起始参数限制为找到的最后一个位置。然后每个循环最多采用log N步骤来查找下一个值,其中N是仍然是候选元素的其余元素。

生成起始值就像在第一个值上调用.replace(microsecond=0)一样简单;结束值只是排序输入中的最后一个值;只要您的“当前”位置低于结尾,添加一秒并找到其插入点;它之前的值是要产生的值。

import bisect
import datetime

def generate_last(dts):
    current = dts[0].replace(microsecond=0)
    end = dts[-1]
    pos = 0
    while current < end:
        current += datetime.timedelta(seconds=1)
        pos = bisect.bisect(dts, current, lo=pos)
        yield dts[pos - 1]

演示:

>>> import bisect
>>> import datetime
>>> def generate_last(dts):
...     current = dts[0].replace(microsecond=0)
...     end = dts[-1]
...     pos = 0
...     while current < end:
...         current += datetime.timedelta(seconds=1)
...         pos = bisect.bisect(dts, current, lo=pos)
...         yield dts[pos - 1]
... 
>>> dts = [datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
...        datetime.datetime(2014, 8, 15, 13, 1, 42, 158749),
...        datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
...        datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
...        datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]
>>> pprint(list(generate_last(dts)))
[datetime.datetime(2014, 8, 15, 13, 1, 41, 658749),
 datetime.datetime(2014, 8, 15, 13, 1, 42, 258749),
 datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
 datetime.datetime(2014, 8, 15, 13, 1, 43, 658749),
 datetime.datetime(2014, 8, 15, 13, 1, 45, 658749)]