-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtimer.py
More file actions
124 lines (106 loc) · 3.89 KB
/
timer.py
File metadata and controls
124 lines (106 loc) · 3.89 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
import datetime
from time import sleep
class WAIT:
"""
Class with constant variables, so no magic number is necessary
"""
__slots__ = ()
PRECISION_THRESHOLD = 0
HOUR = 1
MIN = 2
SEC = 3
USEC = 4
class Timer:
"""
Timer class that sleeps until system time or until given duration passes
"""
IDC = 1
""""I Don't Care" variable - used when field does not matter"""
def __init__(self):
self._timeout = datetime.datetime.now().time()
self._type = None
@classmethod
def fromClock(cls, hour=0, minute=0, second=0, microsecond=0):
"""
:param hour: [0, 23]
:param minute: [0, 59]
:param second: [0, 59]
:param microsecond: [0, 99999]
:return: Timer that waits until given system time
"""
t = Timer()
t._timeout = t._timeout.replace(hour, minute, second, microsecond)
t._type = 'clock'
return t
@classmethod
def fromDuration(cls, hour=0, minute=0, second=0, microsecond=0):
"""
:param hour: [0, 23]
:param minute: [0, 59]
:param second: [0, 59]
:param microsecond: [0, 99999]
:return: Timer that waits for given duration (must be greater that zero)
"""
if hour < 0 or hour > 23:
raise ValueError("Wrong hour value. Must be [0, 23]")
if minute < 0 or minute > 59:
raise ValueError("Wrong minute value. Must be [0, 59]")
if second < 0 or second > 59:
raise ValueError("Wrong second value. Must be [0, 59]")
if microsecond < 0 or microsecond > 99999:
raise ValueError("Wrong microsecond value. Must be [0, 99999]")
if hour + minute + second + microsecond == 0:
raise ValueError("Zero time value.")
t = Timer()
timeout = datetime.timedelta(hours=hour, minutes=minute, seconds=second, microseconds=microsecond)
t._timeout = timeout
t._type = 'duration'
return t
def waitForTimeout(self):
"""
:return: True when given time elapses, false if interrupted
"""
if self._type == 'duration':
now = datetime.datetime.now()
self._timeout = (now + self._timeout).time()
try:
while self.getWaitTime() == WAIT.MIN:
self._timerSleep(60)
while self.getWaitTime() == WAIT.SEC:
self._timerSleep(1)
while 1:
if self._getDeltaTime() < datetime.timedelta.resolution:
return True
except Exception as e:
print(e)
return False
@staticmethod
def _timerSleep(time):
sleep(time)
def getWaitTime(self):
"""
Check for how much time Timer should sleep before next check
:return: WAIT ENUM
"""
delta = self._getDeltaTime()
if delta < datetime.timedelta():
delta += datetime.timedelta(days=1)
return self._checkInterval(delta)
def _getDeltaTime(self):
now = datetime.datetime.now().time()
start = datetime.datetime(Timer.IDC, Timer.IDC, Timer.IDC, now.hour,
now.minute, now.second, now.microsecond)
u = self._timeout.microsecond if self._timeout.microsecond != now.microsecond \
else (self._timeout.microsecond + 1) % 1000000
stop = datetime.datetime(Timer.IDC, Timer.IDC, Timer.IDC, self._timeout.hour,
self._timeout.minute, self._timeout.second, u)
delta = stop - start
return delta
@staticmethod
def _checkInterval(delta):
h, m, s, u = map(int, str(delta).replace('.', ':').split(':'))
if h > 0 or (h == 0 and m > WAIT.PRECISION_THRESHOLD):
return WAIT.MIN
if m > 0 or (m == 0 and s > WAIT.PRECISION_THRESHOLD):
return WAIT.SEC
return WAIT.USEC