How about using regex 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
Part of regex in parts:
^ : start of line(\d+) : 1st digit recorded as group 1(?::([0-5]?\d)(?::([0-5]?\d))?)? additional part:(?:...) - not an exciting group: matches literal :([0-5]?\d) optional digit 0-5, followed by the digit recorded as group 2- there is no capture in the first group:
(?::([0-5]?\d))? which does not necessarily coincide with the second : followed by an optional digit 0-5, followed by a digit; and capturing numbers in group 3 - and finally
$ matches the end of the line. Strictly, ^ is not required at the beginning, since match binds a match at the beginning; however, $ is required, because otherwise the match will not be fixed at the end of the line! (Python 3.4 added re.fullmatch to fix this.)
match.groups() will be a tuple of 3 elements; mismatch groups will be returned as None .
source share