-
Notifications
You must be signed in to change notification settings - Fork 3
/
timer.py
150 lines (121 loc) · 3.91 KB
/
timer.py
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
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
import time
class Timer:
"""
Simple Timer
start(duration=None, keep_running=False)
stop(duration=None)
is_stopped()
is_running(duration=None)
is_expired(duration=None)
get_elapsed()
get_remaining()
"""
def __init__(self, duration=None):
"""
:param duration: seconds
"""
self.duration = duration # timer duration in seconds
self._start_time = None # start timestamp: time.perf_counter()
def start(self, duration=None, restart=True):
if self._start_time and not restart:
pass
else:
self.update_duration(duration)
if self.duration is not None:
self._start_time = time.perf_counter()
def stop(self, duration=None):
self.update_duration(duration)
self._start_time = None
def is_stopped(self):
return True if self._start_time is None else False
def is_running(self):
t = time.perf_counter()
if self._start_time and t < self._start_time + self.duration: # check elapsed time
return True
else:
return False
def is_expired(self):
t = time.perf_counter()
if self._start_time and t >= self._start_time + self.duration: # check elapsed time
return True
else:
return False
def update_duration(self, duration):
if duration is not None: # set new duration
self.duration = duration
if self.duration is None: # if duration is not specified, timer is disabled
self._start_time = None
def get_elapsed(self):
try:
return min(time.perf_counter() - self._start_time, self.duration) # calculate elapsed time and limit
except:
return 0
def get_remaining(self):
try:
return max(self._start_time + self.duration - time.perf_counter(), 0) # calculate remaining time
except:
return 0 if self.duration is None else self.duration
def get_info(self):
if self.is_stopped():
return "stop"
elif self.is_running():
return "run ({}/{})".format(round(self.get_elapsed()), self.duration)
elif self.is_expired():
return "expired ({})".format(self.duration)
else:
return "error"
def set_expired(self):
self._start_time = time.perf_counter() - self.duration
class IntervalTimer:
"""
Simple interval timer. Aligned to system time
"""
def __init__(self, interval):
"""
Init
:param interval: seconds
"""
self.interval = interval
self.t = None
def __call__(self):
"""
Run timer.
:return: True if interval is jumped over else False
"""
t = int(time.time() / self.interval)
if self.t is None:
self.t = t
r = t != self.t
self.t = t
return r
def get_elapsed(self):
"""
Get time elapsed since last interval
:return: seconds
"""
try:
return time.time() - self.t * self.interval
except:
return 0
def get_remaining(self):
"""
Get time remaining to next interval
:return: seconds
"""
try:
return (self.t + 1) * self.interval - time.time()
except:
return 0
if __name__ == "__main__":
# === Demo: Timer ====
# tmr = Timer(4)
# print("{} {} {:.1f} {:.1f}".format(tmr.is_running(), tmr.is_expired(), tmr.get_elapsed(), tmr.get_remaining()))
# tmr.start()
# while True:
# print("{} {} {:.1f} {:.1f}".format(tmr.is_running(), tmr.is_expired(), tmr.get_elapsed(), tmr.get_remaining()))
# time.sleep(0.5)
# === Demo: Interval ====
tmr = IntervalTimer(20)
while True:
print(tmr(), tmr.get_elapsed(), tmr.get_remaining())
time.sleep(0.5)