What is the standard way to add N seconds to datetime.time in Python?

Go To StackoverFlow.com

297

Given a datetime.time value in Python, is there a standard way to add an integer number of seconds to it, so that 11:34:59 + 3 = 11:35:02, for example?

These obvious ideas don't work:

>>> 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'

In the end I have written functions like this:

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)

I can't help thinking that I'm missing an easier way to do this though.

Related

2008-09-19 07:19
by Paul Stephenson
related Python issue: datetime.time support for '+' and '-'jfs 2014-12-29 01:21


415

You can use full datetime variables with timedelta, and by providing a dummy date then using time to just get the time value.

For example:

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()

results in the two values, three seconds apart:

11:34:59
11:35:02

You could also opt for the more readable

b = a + datetime.timedelta(seconds=3)

if you're so inclined.


If you're after a function that can do this, you can look into using addSecs below:

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

This outputs:

 09:11:55.775695
 09:16:55
2008-09-19 07:54
by paxdiablo
To avoid OverflowErrors, I'd recommend using a different dummy date, eg a couple of years later: datetime(101,1,1,11,34,59). If you try subtracting a large timedelta from the date above, you'll get an "OverflowError: date value out of range" error as the year for a datetime object cannot be smaller than - pheelicks 2011-11-29 05:23
@pheelicks, done, albeit a little late, not exactly agile response times :-) Since I had to fix another bug in my code, I thought I'd incorporate your suggestion at the same time - paxdiablo 2013-01-15 01:20


45

As others here have stated, you can just use full datetime objects throughout:

sometime = get_some_time() # the time to which you want to add 3 seconds
later = (datetime.combine(date.today(), sometime) + timedelta(seconds=3)).time()

However, I think it's worth explaining why full datetime objects are required. Consider what would happen if I added 2 hours to 11pm. What's the correct behavior? An exception, because you can't have a time larger than 11:59pm? Should it wrap back around?

Different programmers will expect different things, so whichever result they picked would surprise a lot of people. Worse yet, programmers would write code that worked just fine when they tested it initially, and then have it break later by doing something unexpected. This is very bad, which is why you're not allowed to add timedelta objects to time objects.

2008-09-19 13:47
by Eli Courtwright


18

One little thing, might add clarity to override the default value for seconds

>>> b = a + datetime.timedelta(seconds=3000)
>>> b
datetime.datetime(1, 1, 1, 12, 24, 59)
2008-09-19 08:08
by unmounted
I like this one. Nice and clear with the specified argument - Vigrond 2014-07-03 13:19


9

Thanks to @Pax Diablo, @bvmou and @Arachnid for the suggestion of using full datetimes throughout. If I have to accept datetime.time objects from an external source, then this seems to be an alternative add_secs_to_time() function:

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()

This verbose code can be compressed to this one-liner:

(datetime.datetime.combine(datetime.date(1, 1, 1), timeval) + datetime.timedelta(seconds=secs_to_add)).time()

but I think I'd want to wrap that up in a function for code clarity anyway.

2008-09-19 09:40
by Paul Stephenson
Thanks - great ide - Anupam 2018-03-25 06:33


6

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. When you go past midnight, it wraps around zero. Now, "What time will it be, 24 hours from now" has a lot of corner cases, including daylight savings time, leap seconds, historical timezone changes, and so on. But sometimes you really do need the simple case, and that's what this will do.

Your example would be written:

>>> import datetime
>>> import nptime
>>> nptime.nptime(11, 34, 59) + datetime.timedelta(0, 3)
nptime(11, 35, 2)

nptime inherits from datetime.time, so any of those methods should be usable, too.

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

2011-07-27 03:49
by rescdsk


4

You cannot simply add number to datetime because it's unclear what unit is used: seconds, hours, weeks...

There is timedelta class for manipulations with date and time. datetime minus datetime gives timedelta, datetime plus timedelta gives datetime, two datetime objects cannot be added although two timedelta can.

Create timedelta object with how many seconds you want to add and add it to datetime object:

>>> from datetime import datetime, timedelta
>>> t = datetime.now() + timedelta(seconds=3000)
>>> print(t)
datetime.datetime(2018, 1, 17, 21, 47, 13, 90244)

There is same concept in C++: std::chrono::duration.

2018-01-18 07:30
by user2387567
please ALWAYS add explanations, newcomers might not have a clue what you are doing here - Gerhard Barnard 2018-01-18 09:10


1

Try adding a datetime.datetime to a datetime.timedelta. If you only want the time portion, you can call the time() method on the resultant datetime.datetime object to get it.

2008-09-19 07:29
by Nick Johnson


1

For completeness' sake, here's the way to do it with arrow (better dates and times for Python):

sometime = arrow.now()
abitlater = sometime.shift(seconds=3)
2017-10-09 19:41
by Bart Van Loon
Ads