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)

Свойство .days и остальные у разницы между будущей (прошлой) и текущей (или какой другой). Можешь закрывать

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

days есть только у дельт, но у них нет готовых часов и минут. Поэтому и спрашиваю.

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

Only days, seconds and microseconds are stored internally.

Ну то есть не хватает часов-минут-секунд.

h = timedelta.seconds // 3600
m = (timedelta.seconds % 3600) // 60
s = timedelta.seconds % 60
neumond
()
Ответ на: комментарий от 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
()

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

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

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

neumond
()
Ответ на: комментарий от olegd
>>> a
datetime.datetime(2024, 5, 29, 13, 39, 54, 714682)
>>> b
datetime.datetime(2024, 5, 29, 13, 40, 4, 537771)
>>> d = b - a
>>> d
datetime.timedelta(seconds=9, microseconds=823089)
>>> str(d)
'0:00:09.823089'
>>> 


Не поможет?

urxvt ★★★★★
()

написать свою и ок. она еще и быстрее будет, ибо не будет разбазаривать время на переформатирование форматов.

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

Не поможет?

Спасибо. Вот пример получше:

>>> str(datetime.timedelta(days=4, seconds=3729, microseconds=823089))
'4 days, 1:02:09.823089'
olegd ★★★
() автор топика
Ответ на: комментарий от neumond

нет никаких batteries included

Оказалось, есть просто __str__. Но результат меня не устроил :)

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

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

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

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

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

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

Это простейший паттерн перевода в систему счисления с нефиксированным основанием

buddhist ★★★★★
()

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

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

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

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

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

Rrule, dateutil, arrow

upcFrost ★★★★★
()
Ответ на: комментарий от 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 ★★★★★
()
Для того чтобы оставить комментарий войдите или зарегистрируйтесь.