首页 > 解决方案 > 获取重复时间的日期时间对象列表

问题描述

问题:

我有这个特定时间的列表,例如:

repeat = ['8:15','14:28','19:43','1:21']

现在我正在尝试创建一个函数,该函数将输出n个日期时间对象的列表,如下所示:

>>> import datetime
>>> 
>>> datetime.datetime.now()
datetime.datetime(2018, 10, 30, 17, 5, 55, 908000) # 2018-10-30 17:05:55
>>> 
>>> output = magic(repeat, how_many=3) # <---
>>> output
[datetime.datetime(2018, 10, 30, 19, 43), datetime.datetime(2018, 10, 31, 1, 21), datetime.datetime(2018, 10, 31, 8, 15)]
>>> 
>>> 
>>> for i in output:
>>>     print( i.strftime("%Y-%m-%d %H:%M:%S") )

2018-10-30 19:43:00
2018-10-31 01:21:00
2018-10-31 08:15:00

我的进步:

所以我用这个解决方案解决了这个问题:

def next(datetime_object, repeat):
    # this function should calculate the next datetime from the datetime_object

    return next_datetime_object

def magic(repeat, how_many=10):
    converted = []
    for i in repeat:
        converted.append( datetime.datetime.strptime(i, '%H:%M') )

    now = datetime.datetime.now()

    output = [ next(now,converted) ]

    while len(output) < how_many:
        output.append(
            next(output[-1] ,converted)
            )

    return output

虽然我陷入了创建这个next()应该计算下一个日期时间对象的函数。

另外,如果有人有任何其他比我更好的替代解决方案,请与我分享。


编辑1(只是为了澄清)

输入:repeat = ['8:15','14:28','19:43','1:21']

功能:magic(repeat, how_many=3)

输出:[ datetime.datetime(2018, 10, 30, 19, 43), datetime.datetime(2018, 10, 31, 1, 21), datetime.datetime(2018, 10, 31, 8, 15) ]

注意:输出取决于电流datetime.datetime.now()。在上面的例子中,当前时间是datetime.datetime(2018, 10, 30, 17, 5, 55, 908000)

标签: pythonpython-3.xdatetimerepeatpython-datetime

解决方案


您想创建datetime.time()对象,然后使序列循环itertools.cycle()并与objects组合datetime.date

import datetime
from itertools import cycle, product, repeat
from bisect import bisect

def datetime_series(*timestrings, reference=None):
    times = sorted(datetime.time(*map(int, t.split(':'))) for t in timestrings)
    if reference is None:
        reference = datetime.datetime.now()
    date, tnow = reference.date(), reference.time()

    next_pos = bisect(times, tnow)  # index of next time object to use
    times = cycle(times + [None])
    for _ in range(next_pos):  # skip forward across the time objects
        next(times)

    for time in times:
        if time is None:
            # next day
            date += datetime.timedelta(days=1)
            time = next(times)
        yield datetime.datetime.combine(date, time)

上面使用None作为哨兵来检测日期值需要增加一个步骤,并且时间字符串被接受为单独的参数,并且您可以传入不同的参考日期(默认是使用now)。

它也是一个无穷无尽的生成器,因此您可以逐步迭代它,或者使用它itertools.slice()来限制结果的数量。

就个人而言,我会改变使函数接受datetime.time()对象而不是传入字符串,因此您只需对参数进行排序,而无需解析并从那里开始。

演示:

>>> from itertools import islice
>>> from pprint import pprint
>>> import datetime
>>> datetime.datetime.now()
datetime.datetime(2018, 10, 30, 17, 39, 46, 91967)
>>> m = datetime_series('8:15', '14:28', '19:43', '1:21')
>>> next(m)
datetime.datetime(2018, 10, 30, 19, 43)
>>> next(m)
datetime.datetime(2018, 10, 31, 1, 21)
>>> m = datetime_series('8:15', '14:28', '19:43', '1:21')
>>> ten_results = list(islice(m, 10))
>>> pprint(ten_results)
[datetime.datetime(2018, 10, 30, 19, 43),
 datetime.datetime(2018, 10, 31, 1, 21),
 datetime.datetime(2018, 10, 31, 8, 15),
 datetime.datetime(2018, 10, 31, 14, 28),
 datetime.datetime(2018, 10, 31, 19, 43),
 datetime.datetime(2018, 11, 1, 1, 21),
 datetime.datetime(2018, 11, 1, 8, 15),
 datetime.datetime(2018, 11, 1, 14, 28),
 datetime.datetime(2018, 11, 1, 19, 43),
 datetime.datetime(2018, 11, 2, 1, 21)]
>>> question_1 = datetime.datetime(2008, 7, 31, 21, 26, 37)  # https://meta.stackexchange.com/a/30138
>>> question_1_series = datetime_series('8:15', '14:28', '19:43', '1:21', reference=question_1)
>>> pprint(list(islice(question_1_series, 10)))
[datetime.datetime(2008, 8, 1, 1, 21),
 datetime.datetime(2008, 8, 1, 8, 15),
 datetime.datetime(2008, 8, 1, 14, 28),
 datetime.datetime(2008, 8, 1, 19, 43),
 datetime.datetime(2008, 8, 2, 1, 21),
 datetime.datetime(2008, 8, 2, 8, 15),
 datetime.datetime(2008, 8, 2, 14, 28),
 datetime.datetime(2008, 8, 2, 19, 43),
 datetime.datetime(2008, 8, 3, 1, 21),
 datetime.datetime(2008, 8, 3, 8, 15)]

推荐阅读