93

Basically I have the inverse of this problem: Python Time Seconds to h:m:s

I have a string in the format H:MM:SS (always 2 digits for minutes and seconds), and I need the integer number of seconds that it represents. How can I do this in python?

For example:

  • "1:23:45" would produce an output of 5025
  • "0:04:15" would produce an output of 255
  • "0:00:25" would produce an output of 25

etc

1

15 Answers 15

142
def get_sec(time_str):
    """Get seconds from time."""
    h, m, s = time_str.split(':')
    return int(h) * 3600 + int(m) * 60 + int(s)


print(get_sec('1:23:45'))
print(get_sec('0:04:15'))
print(get_sec('0:00:25'))
Sign up to request clarification or add additional context in comments.

2 Comments

It's very nice and clear and compact but fails if the time does not have all the components, e.g. '3' or "1:21", or if the seconds part is a float. For these cases maybe the tzot solution below could be better fit, using float values
The last part being float can be easily fixed by using float(s) instead.
69
ts = '1:23:45'
secs = sum(int(x) * 60 ** i for i, x in enumerate(reversed(ts.split(':'))))
print(secs)

5 Comments

That's a really interesting technique. Thanks for sharing this.
What does that double-star operator do?
@hughes Exponentiation.
This superior code will also handle s and m:s strings like "53" and "2:41" correctly
This is great. Change int(x) to float(x) and it'll handle decimal seconds, plus it doesn't need a leading zero for hour. VTT timestamps omit the leading 0 hour until hour > 1.
17

Using datetime module

import datetime
t = '10:15:30'
h,m,s = t.split(':')
print(int(datetime.timedelta(hours=int(h),minutes=int(m),seconds=int(s)).total_seconds()))

Output: 36930

3 Comments

What does the output from your code look like given the OP's example input?
You don't need re for this. Strings have a split method: str.split(). Much cleaner to just use t.split(':') instead of re.split(':', t).
I ended up using this solution, as it seemed to be the most standard way of doing it. I slightly altered the conversion of h,m,s to int using a comprehension list to make the conversion line cleaner, which ends up looking like this: h, m, s = [int(x) for x in t.split(':')].
14

Without many checks, and assuming it's either "SS" or "MM:SS" or "HH:MM:SS" (although not necessarily two digits per part):

def to_seconds(timestr):
    seconds= 0
    for part in timestr.split(':'):
        seconds= seconds*60 + int(part, 10)
    return seconds

>>> to_seconds('09')
9
>>> to_seconds('2:09')
129
>>> to_seconds('1:02:09')
3729

This is a different “spelling” of FMc's answer :)

2 Comments

Really useful. Thanks. I like that you take into account for shorter strings that only contain seconds or minutes... 👍
This is the best solution here. How come it's so under-voted!? It considers strings with missing minutes or hours part in a neat, single function, and without using any extra library. Kudos!
7

Using datetime module is also posible and more robust

import datetime as dt

def get_total_seconds(stringHMS):
   timedeltaObj = dt.datetime.strptime(stringHMS, "%H:%M:%S") - dt.datetime(1900,1,1)
   return timedeltaObj.total_seconds()

datetime.strptime parses the string according to format %H:%M:%S, and it creates a datetime object as year 1900, month1, day 1, hour H, minute M, and second S.

That's why to get the total of seconds is necessary to subtract the year, month and day.

print(get_total_seconds('1:23:45'))
>>> 5025.0

print(get_total_seconds('0:04:15'))
>>> 255.0

print(get_total_seconds('0:00:25'))
>>>25.0

1 Comment

This worked for me. I used "%H:%M:%S.%f" instead to handle decimal seconds
4

For %H:%M:%S.%f

def get_sec(time_str):
    h, m, s = time_str.split(':')
    return int(h) * 3600 + int(m) * 60 + float(s)

Comments

2

You can use lambda and reduce a list and the fact that m=60s and h=60m. (see "Reducing a List" at http://www.python-course.eu/lambda.php)

timestamp = "1:23:45"
seconds = reduce(lambda x, y: x*60+y, [int(i) for i in (timestamp.replace(':',',')).split(',')])

Comments

2

You can split the time into a list and add each individual time component, multiplying the hours component by 3600 (the number of seconds in an hour) and the minutes component by 60 (number of seconds in a minute), like:

timeInterval ='00:35:01'
list = timeInterval.split(':')
hours = list[0]
minutes = list[1]
seconds = list[2]
total = (int(hours) * 3600 + int(minutes) * 60 + int(seconds))
print("total = ", total)

Comments

2

I didn't really like any of the given answers, so I used the following:

def timestamp_to_seconds(t):
    return sum(float(n) * m for n,
               m in zip(reversed(time.split(':')), (1, 60, 3600))
               )

Comments

1
parts = time_string.split(":")
seconds = int(parts[0])*(60*60) + int(parts[1])*60 + int(parts[2])

1 Comment

Almost worked, I had to use int(...) as taskinoor suggested for it to work properly.
1

Expanding on @FMc's solution which embodies half of Horner's method. Advantage of Horner's method: Skip reversing the list, avoid power calculation.

from functools import reduce

timestamp = "1:23:45"
seconds = reduce(lambda s, d: s * 60 + int(d), timestamp.split(":"), 0)

or, if you dislike reduce (as does Guido van Rossum and @0xc0de below):

timestamp = "1:23:45"
seconds = 0
for d in timestamp.split(":"):
    seconds = seconds * 60 + int(d)

If you prefer zip (as does @nathan-rice below):

from itertools import accumulate, repeat
from operator import mul

def timestamp_to_seconds(t):
    return sum(int(n) * m for n, m in
       zip(reversed(t.split(":")), accumulate(repeat(60), func=mul, initial=1)))

1 Comment

Goes a step forward in performance, but maybe a step backwards in readability, unless all your co-workers/fellow code readers are good with reduced readability. +1 for those cases, I am not a fan of reduce() though and would prefer to avoid these.
1

I liked tzot's answer above the best for my purposes because my H:M:S are human created and the can have float seconds part Here is my small modification

def hms_to_seconds(timestr:str)->float:
    """Get seconds from time.

    :param timestr: hh:mm:ss.xxx string or mm:s.xxx or simply s.xxx where xxx is the fraction of seconds
    :returns: time in float seconds
    """
    seconds= 0.
    for part in timestr.split(':'):
        seconds= seconds*60. + float(part)
    return seconds

>>> hms_to_seconds('3.00')
3.0
>>> hms_to_seconds('1:3.00')
63.0
>>> hms_to_seconds('1:0:3.5')
3603.5

Comments

0

Another alternative if you have days on string:

def duration2sec(string):
    if "days" in string:
        days = string.split()[0]
        hours = string.split()[2].split(':')
        return int(days) * 86400 + int(hours[0]) * 3600 + int(hours[1]) * 60 + int(hours[2])
    else:
        hours = string.split(':')
        return int(hours[0]) * 3600 + int(hours[1]) * 60 + int(hours[2])

2 Comments

The question asks for converting H:MM:SS time string to seconds not to convert days to to secs. Please have try to reword your answer for the question
The example is functional, else part will do that. But I agree that the simpler the better.
0

Just a simple generalization to the great response of taskinoor

In the context of my problem the format is similar, but includes AM or PM.

Format 'HH:MM:SS AM' or 'HH:MM:SS PM'

For this case the function changes to:

def get_sec(time_str):
"""Get Seconds from time."""
if 'AM' in time_str:
    time_str = time_str.strip('AM')
    h, m, s = time_str.split(':')
    seconds = int(h) * 3600 + int(m) * 60 + int(s)
if 'PM' in time_str:
    time_str = time_str.strip('PM')
    h, m, s = time_str.split(':')
    seconds = (12 + int(h)) * 3600 + int(m) * 60 + int(s)

return seconds 

Comments

0

In Pandas using @JayRizzo 's cool function and a list comprehension:

def get_sec(time_str):
    """Get Seconds from time."""
    h, m, s = time_str.split(':')
    return int(h) * 3600 + int(m) * 60 + int(s)

df['secs']=[get_sec(x) for x in df['original_time_string']]

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.