7

Sometimes I get a string like "02:40" indicating 2 hours and 40 minutes. I'd like to parse that string into the number of minutes (160 in this case) using Python.

Sure, I can parse the string and multiply the hours by 60, but is there something in the standard lib that does this?

Ram Rachum
  • 84,019
  • 84
  • 236
  • 374
  • Unlikely. Standard libraries cater for the common case and in this case you can easily solve it with code. So why should the Python creators bother? – Joey Jul 24 '11 at 16:27
  • why do you need it to use std lib? Because of the separator? – JBernardo Jul 24 '11 at 17:57
  • I believe that if you're doing something technical in your code that's more than a line of code long and even a little bit complicated, you should have a function for it. Maybe I'll make one. – Ram Rachum Jul 24 '11 at 20:36

6 Answers6

10

Other than the following, string parsing (or if you want to be even slower for something so simple, use the re module) is the only way I can think of if you rely on the standard library. TimeDelta doesn't seem to suit the task.

>>> import time
>>> x = "02:40"
>>> t = time.strptime(x, "%H:%M")
>>> minutes = t.tm_hour * 60 + t.tm_min
>>> minutes
160
10

Personally, I think simply parsing the string is far easier to read:

>>> s = '02:40'
>>> int(s[:-3]) * 60 + int(s[-2:])
160

Note that using negative indexing means it will handle strings without the leading zero on the hour:

>>> s = '2:40'
>>> int(s[:-3]) * 60 + int(s[-2:])
160

You could also use the split() function:

>>> hours, minutes = s.split(':')
>>> int(hours) * 60 + int(minutes)
160

Or use the map() function to convert the pieces to integers:

>>> hours, minutes = map(int, s.split(':'))
>>> hours * 60 + minutes
160

Speed

Using the timeit module indicates it is also faster than other methods proposed here:

>>> import timeit
>>> parsetime = timeit.timeit("mins = int(s[:-3]) * 60 + int(s[-2:])", "s='02:40'", number=100000) / 100000
>>> parsetime
9.018449783325196e-06

The split() method is a bit slower:

>>> splittime = timeit.timeit("hours,minutes = s.split(':'); mins=int(hours)*60 + int(minutes)", "s='02:40'", number=100000)/100000
>>> splittime
1.1217889785766602e-05
>>> splittime/parsetime
1.2438822697120402

And using map() a bit slower again:

>>> splitmaptime = timeit.timeit("hours,minutes = map(int, s.split(':')); mins=hours*60 + minutes", "s='02:40'", number=100000)/100000
>>> splitmaptime
1.3971350193023682e-05
>>> splitmaptime/parsetime
1.5491964282881776

John Machin's map and sum is about 2.4 times slower:

>>> summaptime = timeit.timeit('mins=sum(map(lambda x, y: x * y, map(int, "2:40".split(":")), [60, 1]))', "s='02:40'", number=100000) / 100000
>>> summaptime
2.1276121139526366e-05
>>> summaptime/parsetime
2.43

Chrono Kitsune's strptime()-based answer is ten times slower:

>>> strp = timeit.timeit("t=time.strptime(s, '%H:%M');mins=t.tm_hour * 60 + t.tm_min", "import time; s='02:40'", number=100000)/100000
>>> strp
9.0362770557403569e-05
>>> strp/parsetime
10.019767557444432
Blair
  • 15,356
  • 7
  • 46
  • 56
  • 1
    The `.split` solution is my favorite up to now. But I'm still pretty disappointed that Python doesn't come with a function that parses hour strings. – Ram Rachum Jul 27 '11 at 10:37
4

See http://webcache.googleusercontent.com/search?q=cache:EAuL4vECPBEJ:docs.python.org/library/datetime.html+python+datetime&hl=en&client=firefox-a&gl=us&strip=1 since the main Python site is having problems.

The function you want is datetime.strptime or time.strptime, which create either a datetime or time object from a string with a time and another string describing the format.

If you want to not have to describe the format, use dateutil, http://labix.org/python-dateutil.

from dateutil.parser import parse
>>> d = parse('2009/05/13 19:19:30 -0400')
>>> d
datetime.datetime(2009, 5, 13, 19, 19, 30, tzinfo=tzoffset(None, -14400))

See How to parse dates with -0400 timezone string in python?

Community
  • 1
  • 1
agf
  • 171,228
  • 44
  • 289
  • 238
  • 2
    Another nice date parser is parsedatetime: http://code.google.com/p/parsedatetime/ – carl Jul 24 '11 at 20:11
1
>>> sum(map(lambda x, y: x * y, map(int, "2:40".split(":")), [60, 1]))
160
John Machin
  • 81,303
  • 11
  • 141
  • 189
0

I'm sure you can represent the given time as a TimeDelta object. From there I am sure there is an easy way to represent the TimeDelta in minutes.

Jon Martin
  • 3,252
  • 5
  • 29
  • 45
-3

There is:

from time import strptime
from calendar import timegm

T = '02:40'
t = timegm(strptime('19700101'+T,'%Y%m%d%H:%M'))
print t

But is this really better than brute calculus ?

.

An exotic solution, that doesn't need importing functions :

T = '02:40'
exec('x = %s' % T.replace(':','*60+'))
print x

edit: corrected second solution to obtain minutes, not seconds

.

Simplest solution

T = '02:40'

print int(T[0:2])*60 + int(T[3:])
eyquem
  • 26,771
  • 7
  • 38
  • 46
  • @John Machin _"Sometimes I get a string like "02:40" indicating ...."_ I see no other 'context' than that. It's rather tiny to justify a downvote. I would prefer you to explain more, instead of taking delight to express things with complicated words I don't understand and I don't find in freedictionary.com – eyquem Jul 25 '11 at 00:48
  • And your first example gives 9600 on my computer, not the 160 expected. – Blair Jul 25 '11 at 00:59
  • Ah ! he wants the result in minutes. Then my first solution doesn't suit to the problem – eyquem Jul 25 '11 at 01:05
  • 1
    @eyquem: It's the pox. Because it's clumsy compared with `eval(T.replace(':', '*60+'))`. Because building code, compiling it and executing it is way over the top for what one presumes is going to be done frequently. Because the bad guys might manage to arrange for T to refer to something like `"666;evil()"` – John Machin Jul 25 '11 at 02:38