diff --git a/pytimeparse/testtimeparse.py b/pytimeparse/testtimeparse.py index efff94f..765f3ff 100644 --- a/pytimeparse/testtimeparse.py +++ b/pytimeparse/testtimeparse.py @@ -119,6 +119,22 @@ class TestTimeparse(unittest.TestCase): self.assertAlmostEqual(timeparse.timeparse('2:04:13:02.266'), 187982.266) + def test_timeparse_granularity_1(self): + '''Check that minute-level granularity applies correctly.''' + self.assertEqual(timeparse.timeparse('4:32', granularity='minutes'), 272*60) + + def test_timeparse_granularity_2(self): + '''Check that minute-level granularity does not apply inappropriately.''' + self.assertEqual(timeparse.timeparse('4:32:02', granularity='minutes'), 272*60+2) + + def test_timeparse_granularity_3(self): + '''Check that minute-level granularity does not apply inappropriately.''' + self.assertAlmostEqual(timeparse.timeparse('7:02.223', granularity='minutes'), 7*60 + 2.223) + + def test_timeparse_granularity_4(self): + '''Check that minute-level granularity does not apply inappropriately.''' + self.assertEqual(timeparse.timeparse('0:02', granularity='seconds'), 2) + def test_timeparse_11(self): '''timeparse test case 11.''' # uptime format diff --git a/pytimeparse/timeparse.py b/pytimeparse/timeparse.py index 0653957..1c4f8b3 100644 --- a/pytimeparse/timeparse.py +++ b/pytimeparse/timeparse.py @@ -84,7 +84,29 @@ MULTIPLIERS = dict([ ('secs', 1) ]) -def timeparse(sval): +def _interpret_as_minutes(sval, mdict): + """ + Times like "1:22" are ambiguous; do they represent minutes and seconds + or hours and minutes? By default, timeparse assumes the latter. Call + this function after parsing out a dictionary to change that assumption. + + >>> import pprint + >>> pprint.pprint(_interpret_as_minutes('1:24', {'secs': '24', 'mins': '1'})) + {'hours': '1', 'mins': '24'} + """ + if ( sval.count(':') == 1 + and '.' not in sval + and (('hours' not in mdict) or (mdict['hours'] is None)) + and (('days' not in mdict) or (mdict['days'] is None)) + and (('weeks' not in mdict) or (mdict['weeks'] is None)) + ): + mdict['hours'] = mdict['mins'] + mdict['mins'] = mdict['secs'] + mdict.pop('secs') + pass + return mdict + +def timeparse(sval, granularity='seconds'): ''' Parse a time expression, returning it as a number of seconds. If possible, the return value will be an `int`; if this is not @@ -106,11 +128,21 @@ def timeparse(sval): 72 >>> timeparse('1.2 seconds') 1.2 + + If granularity is specified as ``minutes``, then ambiguous digits following + a colon will be interpreted as minutes; otherwise they are considered seconds. + + >>> timeparse('1:30') + 90 + >>> timeparse('1:30', granularity='minutes') + 5400 ''' for timefmt in TIMEFORMATS: match = re.match(r'\s*' + timefmt + r'\s*$', sval, re.I) if match and match.group(0).strip(): mdict = match.groupdict() + if granularity == 'minutes': + mdict = _interpret_as_minutes(sval, mdict) # if all of the fields are integer numbers if all(v.isdigit() for v in list(mdict.values()) if v): return sum([MULTIPLIERS[k] * int(v, 10) for (k, v) in