99

I'm trying to do something like this:

time() + timedelta(hours=1)

however, Python doesn't allow it, apparently for good reason.

Does anyone have a simple work around?

Related:

Community
  • 1
  • 1
Antonius Common
  • 2,931
  • 5
  • 32
  • 32

7 Answers7

158

The solution is in the link that you provided in your question:

datetime.combine(date.today(), time()) + timedelta(hours=1)

Full example:

from datetime import date, datetime, time, timedelta

dt = datetime.combine(date.today(), time(23, 55)) + timedelta(minutes=30)
print dt.time()

Output:

00:25:00
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • 9
    It feels a bit like a work-around to enhance the data by irrelevant information. What happens if `today()` is the day before switching to daylight saving times, and the timedelta extends into the different time zone? Is this code affected by locales? – bluenote10 Apr 04 '17 at 20:46
  • 1
    @bluenote10 a naive datetime object is just an integer number of microseconds that is broken-down according to the proleptic Gregorian calendar. In other words, the code in the answer works as is even around, during DST transitions in any local timezone. `date.today()` is used to support both positive and negative timedeltas. `date.min` would work for positive timedeltas. – jfs Apr 05 '17 at 07:03
  • @J.F.Sebastian: That's reassuring, thanks for the update. It still makes me cringe if a function that is supposed to be pure has a side effect. People from the year 9999 will not like this either ;). – bluenote10 Apr 05 '17 at 07:11
  • 3
    @bluenote10 Practicality beats purity. I doubt `datetime.MAXYEAR` will remain 9999 in 9999. – jfs Apr 05 '17 at 07:31
14

If it's worth adding another file / dependency to your project, I've just written a tiny little class that extends datetime.time with the ability to do arithmetic. If you go past midnight, it just wraps around:

>>> from nptime import nptime
>>> from datetime import timedelta
>>> afternoon = nptime(12, 24) + timedelta(days=1, minutes=36)
>>> afternoon
nptime(13, 0)
>>> str(afternoon)
'13:00:00'

It's available from PyPi as nptime ("non-pedantic time"), or on GitHub: https://github.com/tgs/nptime

The documentation is at http://tgs.github.io/nptime/

rescdsk
  • 8,739
  • 4
  • 36
  • 32
8

Workaround:

t = time()
t2 = time(t.hour+1, t.minute, t.second, t.microsecond)

You can also omit the microseconds, if you don't need that much precision.

sth
  • 222,467
  • 53
  • 283
  • 367
  • yes, nice answer. I should have made it trickier, like: time() + timedelta(minutes=30) – Antonius Common Mar 17 '09 at 22:50
  • 7
    If `t == time(23,59)` then this approach won't work. When you add `1` to `t.hour` you'll get `ValueError: hour must be in 0..23` – jfs Mar 17 '09 at 23:20
  • Corrected the syntax error. For the 23:59 case the question is what the real intention of the calculation is, what you really want to get as a result in that case. I assumed it should stay on the same day (or give an error), else you usually would have datetime in the first place... – sth Mar 17 '09 at 23:55
  • 1
    This method caused an error for me because I was adding 1 day to October 31. It is for this reason that you should use `datetime.timedelta(days=1)` to add a day to a datetime object. You will avoid debug land. – Bobort Oct 31 '16 at 13:44
  • Although this answer is missing critical information, I think it is the best "default" approach. The other answers are also missing critical information, but instead of an error, they have the implicit "overflow" to the next/previous date, which could be even more critical (hidden bug that is hard to find). In my use case specifically, that is not what I want, I'd like to have `time.max` if I'm trying to add 1 hour to `t == time(23, 59)`, for example. – felipou Jan 08 '22 at 01:39
  • a shorter way to express this: `t2 = t.replace(hour=t.hour+1)` – Jakub Kukul Oct 24 '22 at 17:09
7

This is a bit nasty, but:

from datetime import datetime, timedelta

now = datetime.now().time()
# Just use January the first, 2000
d1 = datetime(2000, 1, 1, now.hour, now.minute, now.second)
d2 = d1 + timedelta(hours=1, minutes=23)
print d2.time()
Ali Afshar
  • 40,967
  • 12
  • 95
  • 109
  • 1
    +1: for `datetime` module. Otherwise it would require to deal with Overflow errors and such manually. – jfs Mar 17 '09 at 23:25
4

You can change time() to now() for it to work

from datetime import datetime, timedelta
datetime.now() + timedelta(hours=1)
duhaime
  • 25,611
  • 17
  • 169
  • 224
yiming
  • 67
  • 4
1

A little bit late to the party but you can also do something along the lines of:

init_time = time(4,0)
added_time = 8
new_time = datetime.time(init_time.hour+added_time)

Note that you'll need to add in correction code to make sure init+time.hour + added+time do not go above 23,59.

anon
  • 11
  • 1
0

Have you tried relativedelta from the dateutil package? It seems to solve your problem quite nicely.

import datetime
from dateutil import relativedelta

print(datetime.datetime.now() + relativedelta.relativedelta(hours=1))
>>> 2023-05-09 16:35:57.008271

I also use it to manipulate dates, some examples:

# going back one month from today
end_date = datetime.date.today() - relativedelta.relativedelta(months=1)
print(end_date)
>>> 2023-04-09

# going back one month from January 2023
end_date = datetime.date(2023,1,1) - relativedelta.relativedelta(months=1)
print(end_date)
>>> 2022-12-01


Hope it helps!