1"""
2Functions various time manipulations.
3"""
4
5# Import Python
6import logging
7import time
8from datetime import datetime, timedelta
9
10# Import Salt modules
11
12log = logging.getLogger(__name__)
13
14
15def get_timestamp_at(time_in=None, time_at=None):
16    """
17    Computes the timestamp for a future event that may occur in ``time_in`` time
18    or at ``time_at``.
19    """
20    if time_in:
21        if isinstance(time_in, int):
22            hours = 0
23            minutes = time_in
24        else:
25            time_in = time_in.replace("h", ":")
26            time_in = time_in.replace("m", "")
27            try:
28                hours, minutes = time_in.split(":")
29            except ValueError:
30                hours = 0
31                minutes = time_in
32            if not minutes:
33                minutes = 0
34            hours, minutes = int(hours), int(minutes)
35        dt = timedelta(hours=hours, minutes=minutes)
36        time_now = datetime.utcnow()
37        time_at = time_now + dt
38        return time.mktime(time_at.timetuple())
39    elif time_at:
40        log.debug("Predicted at specified as %s", time_at)
41        if isinstance(time_at, (int, float)):
42            # then it's a timestamp
43            return time_at
44        else:
45            fmts = ("%H%M", "%Hh%M", "%I%p", "%I:%M%p", "%I:%M %p")
46            # Support different formats for the timestamp
47            # The current formats accepted are the following:
48            #
49            #   - 18:30 (and 18h30)
50            #   - 1pm (no minutes, fixed hour)
51            #   - 1:20am (and 1:20am - with or without space)
52            for fmt in fmts:
53                try:
54                    log.debug("Trying to match %s", fmt)
55                    dt = datetime.strptime(time_at, fmt)
56                    return time.mktime(dt.timetuple())
57                except ValueError:
58                    log.debug("Did not match %s, continue searching", fmt)
59                    continue
60            msg = "{pat} does not match any of the accepted formats: {fmts}".format(
61                pat=time_at, fmts=", ".join(fmts)
62            )
63            log.error(msg)
64            raise ValueError(msg)
65
66
67def get_time_at(time_in=None, time_at=None, out_fmt="%Y-%m-%dT%H:%M:%S"):
68    """
69    Return the time in human readable format for a future event that may occur
70    in ``time_in`` time, or at ``time_at``.
71    """
72    dt = get_timestamp_at(time_in=time_in, time_at=time_at)
73    return time.strftime(out_fmt, time.localtime(dt))
74