1# -*- coding: utf-8 -*- 2""" 3This function took most of the code from 'parsetime' python library: 4https://pypi.org/project/python-parsetime/ 5 6but code was stripped to provide matching for required time formats only 7""" 8 9import re 10 11YEARS = r"(?P<years>\d+)\s*(?:ys?|yrs?.?|years?)" 12MONTHS = r"(?P<months>\d+)\s*(?:mos?.?|mths?.?|months?)" 13WEEKS = r"(?P<weeks>[\d.]+)\s*(?:w|wks?|weeks?)" 14DAYS = r"(?P<days>[\d.]+)\s*(?:d|dys?|days?)" 15HOURS = r"(?P<hours>[\d.]+)\s*(?:h|hrs?|hours?)" 16MINS = r"(?P<mins>[\d.]+)\s*(?:m|(mins?)|(minutes?))" 17SECS = r"(?P<secs>[\d.]+)\s*(?:s|secs?|seconds?)" 18SEPARATORS = r"[,/]" 19 20OPT = lambda x: r"(?:{x})?".format(x=x) 21OPTSEP = lambda x: r"(?:{x}\s*(?:{SEPARATORS}\s*)?)?".format(x=x, SEPARATORS=SEPARATORS) 22 23TIMEFORMATS = [ 24 r"{YEARS}\s*{MONTHS}\s*{WEEKS}\s*{DAYS}\s*{HOURS}\s*{MINS}\s*{SECS}".format( 25 YEARS=OPTSEP(YEARS), 26 MONTHS=OPTSEP(MONTHS), 27 WEEKS=OPTSEP(WEEKS), 28 DAYS=OPTSEP(DAYS), 29 HOURS=OPTSEP(HOURS), 30 MINS=OPTSEP(MINS), 31 SECS=OPT(SECS), 32 ) 33] 34 35COMPILED_TIMEFORMATS = [ 36 re.compile(r"\s*" + timefmt + r"\s*$", re.I) for timefmt in TIMEFORMATS 37] 38 39MULTIPLIERS = dict( 40 [ 41 ("years", 60 * 60 * 24 * 365), 42 ("months", 60 * 60 * 24 * 30), 43 ("weeks", 60 * 60 * 24 * 7), 44 ("days", 60 * 60 * 24), 45 ("hours", 60 * 60), 46 ("mins", 60), 47 ("secs", 1), 48 ] 49) 50 51 52def uptimeparse(data, format="seconds"): 53 """ 54 Parse a time expression like: 55 2 years, 27 weeks, 3 days, 10 hours, 46 minutes 56 27 weeks, 3 days, 10 hours, 48 minutes 57 58 returning a number of seconds. 59 """ 60 for timefmt in COMPILED_TIMEFORMATS: 61 match = timefmt.match(data) 62 if match and match.group(0).strip(): 63 mdict = match.groupdict() 64 # if all of the fields are integer numbers 65 if all(v.isdigit() for v in list(mdict.values()) if v): 66 if format == "seconds": 67 return ( 68 sum( 69 [ 70 MULTIPLIERS[k] * int(v, 10) 71 for (k, v) in list(mdict.items()) 72 if v is not None 73 ] 74 ), 75 None, 76 ) 77 elif format == "dict": 78 return {k: v for k, v in mdict.items() if v is not None}, None 79 break 80 return data, None 81