I have the fallowing problem,
Im supposed to get user input in the form of 10:10:10 (hh:mm:ss) or 10:10(mm:ss) or 10(ss). Now i need check the fallowing parameters:
mm:ss then the seconds are limited to 0..59 and minutes are unlimited.hh:mm:ss then both seconds and minutes are limited to 0..59 while hours are unlimited.Then return a TimeDelta object.
The naive way is to write multiply if statements to check all this.
But im looking for a smoother way.
val = "11:66:11"
try:
val = map(int, val.split(':'))
except ValueError:
return False
if len(val) == 1:
return val
if len(val) == 2:
if val[1] > 59:
print "Bad seconds"
return False
if len(val) == 3:
if val[2] > 59 or val[1] >59:
print "Bad seconds / minutes"
return False
while len(val) < 3:
split.insert(0,0)
return = timedelta(hours=split[0],minutes=split[1],seconds=split[2])
How about using regular expression here:
import re
import datetime
pattern = re.compile(r'^(\d+)(?::([0-5]?\d)(?::([0-5]?\d))?)?$')
def str2seconds(val):
match = pattern.match(val)
if not match:
raise ValueError("Invalid input: %s" % val)
else:
result = 0
for i in match.groups():
if i is not None:
result *= 60
result += int(i)
return datetime.timedelta(seconds=result)
Example:
>>> print(str2seconds('255'))
0:04:15
>>> print(str2seconds('255:25'))
4:15:25
>>> print(str2seconds('255:25:25'))
10 days, 15:25:25
>>> print(str2seconds('255:25:25:255'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "y.py", line 8, in str2seconds
raise ValueError("Invalid input: %s" % val)
ValueError: Invalid input: 255:25:25:255
>>> print(str2seconds('255:25:60'))
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "y.py", line 8, in str2seconds
raise ValueError("Invalid input: %s" % val)
ValueError: Invalid input: 255:25:60
The regular expression part by part:
^: beginning of string(\d+): 1-n digits, captured as group 1(?::([0-5]?\d)(?::([0-5]?\d))?)? optional part:
(?:...) is a non-capturing group: matches literal :
([0-5]?\d) an optional digit 0-5, followed by a digit, captured as group 2(?::([0-5]?\d))? that optionally matches second : followed by
an optional digit 0-5 followed by a digit; and capturing the digits into group 3$ matches the end of the string. Strictly, ^ at the beginning is not necessary as match anchors the match at the beginning; however the $ is necessary, as otherwise the match is not anchored at the end of the string! (Python 3.4 added the re.fullmatch to fix this.)The match.groups() will be a tuple of 3 items; the non-matching groups will be returned as None.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With