Учитывая значение datetime.time в Python, существует ли стандартный способ добавить к нему целое число секунд, например, 11:34:59 + 3 = 11:35:02?
Эти очевидные идеи не работают:
>>> datetime.time(11, 34, 59) + 3
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'int'
>>> datetime.time(11, 34, 59) + datetime.timedelta(0, 3)
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.timedelta'
>>> datetime.time(11, 34, 59) + datetime.time(0, 0, 3)
TypeError: unsupported operand type(s) for +: 'datetime.time' and 'datetime.time'
В итоге я написал такие функции:
def add_secs_to_time(timeval, secs_to_add):
secs = timeval.hour * 3600 + timeval.minute * 60 + timeval.second
secs += secs_to_add
return datetime.time(secs // 3600, (secs % 3600) // 60, secs % 60)
Я не могу избавиться от мысли, что мне не хватает более простого способа сделать это.






Попробуйте добавить datetime.datetime к datetime.timedelta. Если вам нужна только временная часть, вы можете вызвать метод time() для полученного объекта datetime.datetime, чтобы получить ее.
Вы можете использовать полные переменные datetime с timedelta и, указав фиктивную дату, а затем используя time, чтобы просто получить значение времени.
Например:
import datetime
a = datetime.datetime(100,1,1,11,34,59)
b = a + datetime.timedelta(0,3) # days, seconds, then other fields.
print(a.time())
print(b.time())
приводит к двум значениям с интервалом в три секунды:
11:34:59
11:35:02
Вы также можете выбрать более читаемый
b = a + datetime.timedelta(seconds=3)
если ты так склонен.
Если вам нужна функция, которая может это сделать, вы можете изучить addSecs ниже:
import datetime
def addSecs(tm, secs):
fulldate = datetime.datetime(100, 1, 1, tm.hour, tm.minute, tm.second)
fulldate = fulldate + datetime.timedelta(seconds=secs)
return fulldate.time()
a = datetime.datetime.now().time()
b = addSecs(a, 300)
print(a)
print(b)
Это выводит:
09:11:55.775695
09:16:55
Чтобы избежать OverflowErrors, я бы рекомендовал использовать другую фиктивную дату, например, пару лет спустя: datetime (101,1,1,11,34,59). Если вы попытаетесь вычесть большое значение timedelta из указанной выше даты, вы получите ошибку «OverflowError: значение даты вне диапазона», поскольку год для объекта datetime не может быть меньше 1.
@pheelicks, готово, хотя и немного поздно, не совсем гибкое время отклика :-) Поскольку мне пришлось исправить еще одну ошибку в моем коде, я подумал, что учту ваше предложение в то же время.
Одна мелочь, может добавить ясности, чтобы переопределить значение по умолчанию на секунды
>>> b = a + datetime.timedelta(seconds=3000)
>>> b
datetime.datetime(1, 1, 1, 12, 24, 59)
Мне нравится этот. Красиво и ясно с указанным аргументом.
Спасибо @Pax Diablo, @bvmou и @Arachnid за предложение использовать полные даты во всем. Если мне нужно принимать объекты datetime.time из внешнего источника, то это кажется альтернативной функцией add_secs_to_time():
def add_secs_to_time(timeval, secs_to_add):
dummy_date = datetime.date(1, 1, 1)
full_datetime = datetime.datetime.combine(dummy_date, timeval)
added_datetime = full_datetime + datetime.timedelta(seconds=secs_to_add)
return added_datetime.time()
Этот подробный код можно сжать до однострочного:
(datetime.datetime.combine(datetime.date(1, 1, 1), timeval) + datetime.timedelta(seconds=secs_to_add)).time()
но я думаю, что в любом случае я бы хотел обернуть это функцией для ясности кода.
Как заявляли здесь другие, вы можете просто использовать полные объекты datetime повсюду:
from datetime import datetime, date, time, timedelta
sometime = time(8,00) # 8am
later = (datetime.combine(date.today(), sometime) + timedelta(seconds=3)).time()
Однако я думаю, что стоит объяснить, почему требуются полные объекты datetime. Подумайте, что было бы, если бы я добавил 2 часа до 23:00. Какое правильное поведение? Исключение, потому что у вас не может быть времени больше 23:59? Должен ли он снова обернуться?
Разные программисты ожидают разного, поэтому любой результат, который они выберут, удивит многих. Что еще хуже, программисты писали код, который работал нормально, когда они сначала тестировали его, а потом ломали его, делая что-нибудь неожиданное. Это очень плохо, поэтому вам не разрешено добавлять объекты timedelta к объектам времени.
Очевидно, исключение. Невозможно добавить ВРЕМЯdelta к ВРЕМЯ - глупо.
@ JürgenA.Erhard Интересно, что я «явно» думал, что правильное поведение будет заключаться в том, чтобы обернуть вокруг…
Если в ваш проект стоит добавить еще один файл / зависимость, я только что написал крошечный класс, расширяющий datetime.time способностью выполнять арифметические операции. Когда вы идете за полночь, он возвращается к нулю. Теперь в вопросе «Во сколько это будет время, через 24 часа» есть множество угловых случаев, включая переход на летнее время, дополнительные секунды, исторические изменения часовых поясов и так далее. Но иногда вам действительно нужен простой чехол, и это то, что вам нужно.
Ваш пример будет написан:
>>> import datetime
>>> import nptime
>>> nptime.nptime(11, 34, 59) + datetime.timedelta(0, 3)
nptime(11, 35, 2)
nptime наследуется от datetime.time, поэтому любой из этих методов тоже можно использовать.
Он доступен в PyPi как nptime («непедантичное время») или на GitHub: https://github.com/tgs/nptime.
Вы не можете просто добавить число к datetime, потому что неясно, какая единица измерения используется: секунды, часы, недели ...
Есть класс timedelta для манипуляций с датой и временем. datetime минус datetime дает timedelta, datetime плюс timedelta дает datetime, два объекта datetime не могут быть добавлены, хотя два timedelta могут.
Создайте объект timedelta с указанием количества секунд, которое вы хотите добавить, и добавьте его в объект datetime:
>>> from datetime import datetime, timedelta
>>> t = datetime.now() + timedelta(seconds=3000)
>>> print(t)
datetime.datetime(2018, 1, 17, 21, 47, 13, 90244)
В C++ есть такая же концепция: std::chrono::duration.
пожалуйста, ВСЕГДА добавляйте пояснения, новички могут не понимать, что вы здесь делаете.
Старый вопрос, но я подумал, что добавлю функцию, которая обрабатывает часовые пояса. Ключевые части передают атрибут datetime.time объекта tzinfo в объединение, а затем используют timetz() вместо time() в результирующем фиктивном datetime. Этот ответ частично вдохновлен другими ответами здесь.
def add_timedelta_to_time(t, td):
"""Add a timedelta object to a time object using a dummy datetime.
:param t: datetime.time object.
:param td: datetime.timedelta object.
:returns: datetime.time object, representing the result of t + td.
NOTE: Using a gigantic td may result in an overflow. You've been
warned.
"""
# Create a dummy date object.
dummy_date = date(year=100, month=1, day=1)
# Combine the dummy date with the given time.
dummy_datetime = datetime.combine(date=dummy_date, time=t, tzinfo=t.tzinfo)
# Add the timedelta to the dummy datetime.
new_datetime = dummy_datetime + td
# Return the resulting time, including timezone information.
return new_datetime.timetz()
А вот действительно простой тестовый класс (с использованием встроенного unittest):
import unittest
from datetime import datetime, timezone, timedelta, time
class AddTimedeltaToTimeTestCase(unittest.TestCase):
"""Test add_timedelta_to_time."""
def test_wraps(self):
t = time(hour=23, minute=59)
td = timedelta(minutes=2)
t_expected = time(hour=0, minute=1)
t_actual = add_timedelta_to_time(t=t, td=td)
self.assertEqual(t_expected, t_actual)
def test_tz(self):
t = time(hour=4, minute=16, tzinfo=timezone.utc)
td = timedelta(hours=10, minutes=4)
t_expected = time(hour=14, minute=20, tzinfo=timezone.utc)
t_actual = add_timedelta_to_time(t=t, td=td)
self.assertEqual(t_expected, t_actual)
if __name__ == '__main__':
unittest.main()
В реальной среде никогда не бывает хорошей идеей работать только с time, всегда используйте datetime, даже лучше utc, чтобы избежать конфликтов, таких как ночь, переход на летнее время, разные часовые пояса между пользователем и сервером и т. д.
Поэтому я бы рекомендовал такой подход:
import datetime as dt
_now = dt.datetime.now() # or dt.datetime.now(dt.timezone.utc)
_in_5_sec = _now + dt.timedelta(seconds=5)
# get '14:39:57':
_in_5_sec.strftime('%H:%M:%S')
связанная проблема Python: datetime.time поддержка "+" и "-"