Страницы

Поиск по вопросам

суббота, 21 декабря 2019 г.

Функция возвращающая количество месяцев, дней, недель, часов в секундах

#python #python_3x #алгоритм #рекурсия #timestamp


Мне нужна функция, которая принимает количество секунд и возвращает строку формата


N г. N мес. N нед. N д. N ч.



year = 31536000
month = 2592000
week = 604800
day = 86400
hour = 3600


from math import floor


def parse_time(time_s):
    if time_s == 0:
        return None
    if time_s < hour:
        return 'меньше часа'
    if time_s >= year:
        return '{} г. '.format(floor(time_s / year)) + parse_time(time_s % year)
    if time_s >= month:
        return '{} мес. '.format(floor(time_s / month)) + parse_time(time_s % month)
    elif time_s >= week:
        return '{} нед. '.format(floor(time_s / week)) + parse_time(time_s % week)
    elif time_s >= day:
        return '{} д. '.format(floor(time_s / day)) + parse_time(time_s % day)
    else:
        return '{} ч.'.format(floor(time_s / hour))


Я написал такую функцию, но немного сомневаюсь в её корректности. 

year, month, week, day, hour – колличество секунд.

Примеры запуска:

print(parse_time(2827567.5759670734))  # 1 мес. 2 д. 17 ч.
print(parse_time(269649.6857390404))   # 3 д. 2 ч.

    


Ответы

Ответ 1



Можно без рекурсии сделать: def parse_time(time_s): year = 31536000 month = 2592000 week = 604800 day = 86400 hour = 3600 if time_s == 0: return None if time_s < hour: return 'меньше часа' result = '' if time_s >= year: result += '{} г. '.format(int(time_s / year)) time_s %= year if time_s >= month: result += '{} мес. '.format(int(time_s / month)) time_s %= month if time_s >= week: result += '{} нед. '.format(int(time_s / week)) time_s %= week if time_s >= day: result += '{} д. '.format(int(time_s / day)) time_s %= day if time_s >= hour: result += '{} ч.'.format(int(time_s / hour)) return result Как видно, алгоритм повторяется, и меняется только пара элементов в нем, а значит это легко представить в цикле: def parse_time(time_s): items = [ (31536000, '{} г. '), (2592000, '{} мес. '), (604800, '{} нед. '), (86400, '{} д. '), (3600, '{} ч.'), ] if time_s == 0: return None if time_s < 3600: return 'меньше часа' result = '' for value, fmt in items: if time_s >= value: result += fmt.format(int(time_s / value)) time_s %= value return result Пример: print(parse_time(2827567.5759670734)) # 1 мес. 2 д. 17 ч. assert parse_time(2827567.5759670734) == "1 мес. 2 д. 17 ч." print(parse_time(269649.6857390404)) # 3 д. 2 ч. assert parse_time(269649.6857390404) == "3 д. 2 ч." PS. floor можно заменить на int. Разница между floor и int проявится на отрицательных числах.

Ответ 2



Для простоты можно разделить чистые вычисления и форматирование (ввод/вывод). К примеру, можно реализовать отдельно функцию, которая разделяет секунды на отдельные единицы времени (годы, дни, часы, итд): def broken_down_time( seconds, units=[ ("year", 31536000), ("month", 2592000), ("week", 604800), ("day", 86400), ("hour", 3600), ], ): t = {} for unit, value in units: if seconds >= value: t[unit], seconds = divmod(seconds, value) return t Пример: >>> broken_down_time(2827567) {'month': 1, 'day': 2, 'hour': 17} >>> broken_down_time(269649) {'day': 3, 'hour': 2} От функции, которая форматирует полученное время: def format_time( t, units=[ ("year", "г."), ("month", "мес."), ("week", "нед."), ("day", "д."), ("hour", "ч."), ], ): return " ".join(f"{t[unit]} {unit_ru}" for unit, unit_ru in units if unit in t) Пример: >>> format_time(broken_down_time(seconds=2827567)) '1 мес. 2 д. 17 ч.' Здесь float->int преобразование до вызова функций сделано. Чтобы не дублировать набор единиц времени, можно класс создать, который принимает единицы времени, секунды и позволяет обращаться к отдельным компонентам, выводить локализованное текстовое представление (то есть объединяет приведённые функции). К примеру, как это pendulum.interval делает.

Комментариев нет:

Отправить комментарий