获取重复时间的日期时间对象列表
Get list of datetime object for repeating time
问题:
我有这个具体时间的列表,例如:
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)
您想要创建 datetime.time()
objects, then make the sequence cyclic with itertools.cycle()
and combine these with datetime.date
objects:
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)]
另一个解决方案是创建日期时间对象,直到它到达 how_many。然后对其进行排序,return 前 how_many 项。
示例代码是
import datetime as dt
def magic(repeat, how_many=3):
output = []
now = dt.datetime.now()
next_day = now
while len(output) < how_many:
nextFormated = next_day.strftime("%Y-%m-%d")
next_times = [dt.datetime.strptime(nextFormated + " " + s, "%Y-%m-%d %H:%M") for s in repeat if dt.datetime.strptime(nextFormated + " " + s, "%Y-%m-%d %H:%M") > now]
next_day += dt.timedelta(days=1)
output = output + next_times
output.sort()
return output[:how_many]
repeat = ['8:15','14:28','19:43','1:21']
op = magic(repeat, 10)
print(dt.datetime.now())
print(op)
输出为
2018-10-30 23:07:52.635834
[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), datetime.datetime(2018, 11, 2, 8, 15)]
[Finished in 0.1s]
问题:
我有这个具体时间的列表,例如:
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)
您想要创建 datetime.time()
objects, then make the sequence cyclic with itertools.cycle()
and combine these with datetime.date
objects:
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)]
另一个解决方案是创建日期时间对象,直到它到达 how_many。然后对其进行排序,return 前 how_many 项。
示例代码是
import datetime as dt
def magic(repeat, how_many=3):
output = []
now = dt.datetime.now()
next_day = now
while len(output) < how_many:
nextFormated = next_day.strftime("%Y-%m-%d")
next_times = [dt.datetime.strptime(nextFormated + " " + s, "%Y-%m-%d %H:%M") for s in repeat if dt.datetime.strptime(nextFormated + " " + s, "%Y-%m-%d %H:%M") > now]
next_day += dt.timedelta(days=1)
output = output + next_times
output.sort()
return output[:how_many]
repeat = ['8:15','14:28','19:43','1:21']
op = magic(repeat, 10)
print(dt.datetime.now())
print(op)
输出为
2018-10-30 23:07:52.635834
[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), datetime.datetime(2018, 11, 2, 8, 15)]
[Finished in 0.1s]