Получить список объекта datetime для повторения времени - PullRequest
0 голосов
/ 30 октября 2018

Проблема:

У меня есть этот список определенного времени, например:

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(), которая должна вычислять следующий объект datetime.

Также, если у кого-нибудь есть альтернативное решение, которое лучше моего, поделитесь им со мной.


Редактировать 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)

Ответы [ 2 ]

0 голосов
/ 30 октября 2018

другое решение - создавать объекты даты и времени, пока они не достигнут how_many. Затем отсортируйте его и верните первые элементы 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]
0 голосов
/ 30 октября 2018

Вы хотели бы создать datetime.time() объекты, а затем сделать последовательность циклической с itertools.cycle() и объединить эти с 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 в качестве часового, чтобы определить, что значение даты должно быть увеличено на шаг, а строки времени приняты в качестве отдельных аргументов, и вы можете передать другую контрольную дату (по умолчанию используйте сейчас ).

Это также бесконечный генератор, так что вы можете перебирать его шаг за шагом или использовать 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)]
...