LINUX.ORG.RU

Даты в Питоне

 ,


0

1

Есть набор текстовых дат вида «14.05.24 17:22:40.653». Нужно вычислить разности по времени между ними и вывести в наглядном виде «сутки:часы:минуты:секунды.доли».

Преобразовать текст в дату несложно: datetime.datetime.strptime(date_time_string, '%d.%m.%y %H:%M:%S.%f')
В секунды с начала эпохи аналогично: datetime.datetime.strptime(date_time_string, '%d.%m.%y %H:%M:%S.%f').timestamp()

Но есть ли готовая функция, чтобы преобразовать разность в секундах в сутки-часы-минуты?

Что разность двух datetime.datetime имеет тип datetime.timedelta – знаю. Но datetime.timedelta не имеет готовых методов для выделения часов и минут.

Ответ: datetime.timedelta имеет метод __str__():

>>> str(datetime.timedelta(days=4, seconds=3729, microseconds=823089))
'4 days, 1:02:09.823089'

Но учитывая, что для 0 суток ползёт форматирование, для единообразия таблицы придётся брать
f'{d.days:02}:{d.seconds // 3600:02}:{d.seconds % 3600 // 60:02}:{d.seconds % 60:02}.{d.microseconds:06}'

★★★

Последнее исправление: olegd (всего исправлений: 2)
Ответ на: комментарий от neumond

Ну да. Но надеялся, что «batteries included» под каким-то другим названием, которое я не угадал.

И там ещё надо озаботиться форматированием, в итоге получается что-нибудь вроде f'{d.days}:{d.seconds // 3600:02}:{d.seconds % 3600 // 60:02}:{d.seconds % 60:02}.{d.microseconds:06}'

datetime.timedelta.strftime('%d:%T') смотрелось бы приятнее.

olegd ★★★
() автор топика
Ответ на: комментарий от olegd

Это как раз тот случай когда хорошо, что нет никаких batteries included, потому что strftime это сложная функция из libc, серьёзно завязанная на локали, стандарты и языки. Для таймдельт этого всего нет, и они там не стали изобретать колесо по аналогии, кому надо сделает в 10 строк всё что хотел.

neumond
()
Ответ на: комментарий от cobold

Это таймдельта, в ней нет корректировок времени. Само вычитание, порождающее таймдельту, уже применяет внутри себя все необходимые корректировки, учитывает часовые пояса, переходы на летнее/зимнее время итд.

neumond
()
Ответ на: комментарий от no-dashi-v2

Преобразовываешь обе даты к UNIX epoch (абсолютное время в секундах).

Об этом написал в стартовом посте.

Дальше тривиально как в начальной школе.

А потом вылезают неочевидные шероховатости, и приходится городить велосипед, который сходу и не воспроизведёшь, когда в следующий раз понадобится. Поэтому спросил, нет ли готового обкатанного решения.

olegd ★★★
() автор топика

Но datetime.timedelta не имеет готовых методов для выделения часов и минут.

Подели на 60 и 3600. Таймдельта не умеет с календарём (месяц/год) работать, вот там реально залет, а минуты/часы фигня.

Либо вычитай timestamp, это вообще топорный метод

upcFrost ★★★★★
()
Последнее исправление: upcFrost (всего исправлений: 1)
Ответ на: комментарий от frob
import timeit

def t1():
    for i in range(5000):
        a, b = i // 60, i % 60

def t2():
    for i in range(5000):
        a, b = divmod(i, 60)

print(timeit.timeit(t1, number=10000))  # 3.156
print(timeit.timeit(t2, number=10000))  # 4.055

Чтобы тормозило посильнее? Ладно ещё atan2, но для чего существует divmod для меня загадка.

neumond
()
Ответ на: комментарий от neumond

Вообще в x86 инструкция div/idiv делает именно это. В один регистр складывает частное, в другой остаток. То что в cpython оно реализовано так что, в этом нет смысла, ну может в какой-то другой реализации оно сделано лучше. А может и нет

cobold ★★★★★
()