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