6
6
from .units import Duration
7
7
8
8
9
+ inf = float ("inf" ) # same as math.inf, but compatible with 3.4
10
+
11
+
12
+ def to_timestamp (t ):
13
+ return t .timestamp () if isinstance (t , datetime ) else t
14
+
15
+
16
+ class TimeInterval (object ):
17
+ __slots__ = ("t0" , "t1" )
18
+
19
+ NO_START = - inf
20
+ NO_END = inf
21
+
22
+ def __init__ (self , from_time = NO_START , to_time = NO_END ):
23
+ self .t0 = self .NO_START if from_time is None else to_timestamp (from_time )
24
+ self .t1 = self .NO_END if to_time is None else to_timestamp (to_time )
25
+
26
+ @property
27
+ def start_time (self ):
28
+ if self .t0 > self .NO_START :
29
+ return datetime .fromtimestamp (self .t0 )
30
+
31
+ @property
32
+ def end_time (self ):
33
+ if self .t1 < self .NO_END :
34
+ return datetime .fromtimestamp (self .t1 )
35
+
36
+ @property
37
+ def duration_delta (self ):
38
+ return timedelta (seconds = self .duration ) if self .duration < inf else None
39
+
40
+ @property
41
+ def duration (self ):
42
+ return Duration (self .t1 - self .t0 )
43
+
44
+ def __contains__ (self , t ):
45
+ """
46
+ check if timestamp is within the timer's interval
47
+ """
48
+
49
+ if isinstance (t , Timer ):
50
+ t = t .to_interval ()
51
+
52
+ if isinstance (t , TimeInterval ):
53
+ return self .t0 <= t .t0 and t .t1 <= self .t1
54
+
55
+ t = to_timestamp (t )
56
+ return self .t0 <= t <= self .t1
57
+
58
+ def to_timer (self ):
59
+ assert self .t0 > self .NO_START , "Can't convert a start-less TimeInterval to a Timer"
60
+ t = Timer (self .t0 )
61
+ t .t1 = self .t1 if self .t1 < self .NO_END else None
62
+ return t
63
+
64
+ def render (self ):
65
+ t0 , duration , t1 = self .t0 , self .duration , self .t1
66
+ if (t0 , t1 ) == (self .NO_START , self .NO_END ):
67
+ return "Eternity"
68
+
69
+ parts = ["." , "." ]
70
+
71
+ if t0 > self .NO_START :
72
+ parts [0 ] = time .strftime ("%T" , time .localtime (t0 ))
73
+
74
+ if t1 < self .NO_END :
75
+ parts [- 1 ] = time .strftime ("%T" , time .localtime (self .t1 ))
76
+
77
+ if duration < inf :
78
+ parts .insert (1 , "({})" .format (duration ))
79
+
80
+ return ".." .join (parts )
81
+
82
+ def __str__ (self ):
83
+ return "<TI %s>" % self .render ()
84
+
85
+ def __repr__ (self ):
86
+ return "TimeInterval(%s)" % self .render ()
87
+
88
+ def _repr_pretty_ (self , p , cycle ):
89
+ # used by IPython
90
+ from easypy .colors import MAGENTA
91
+ if cycle :
92
+ p .text ('TimeInterval(...)' )
93
+ return
94
+ p .text (MAGENTA (self .render ()))
95
+
96
+
9
97
class Timer (object ):
10
98
11
99
"""
@@ -26,10 +114,12 @@ class Timer(object):
26
114
# do something ...
27
115
"""
28
116
117
+ __slots__ = ("t0" , "t1" , "expiration" )
118
+
29
119
def __init__ (self , now = None , expiration = None ):
30
120
self .reset (now )
31
121
self .t1 = None
32
- self .expiration = expiration
122
+ self .expiration = None if expiration is None else Duration ( expiration )
33
123
34
124
def reset (self , now = None ):
35
125
self .t0 = now or time .time ()
@@ -43,6 +133,22 @@ def iter(self, sleep=1):
43
133
time .sleep (sleep )
44
134
yield self .remain
45
135
136
+ def to_interval (self ):
137
+ return TimeInterval (self .t0 , self .t1 )
138
+
139
+ def __contains__ (self , timestamp ):
140
+ """
141
+ check if timestamp is within the timer's interval
142
+ """
143
+ timestamp = to_timestamp (timestamp )
144
+ if timestamp < self .t0 :
145
+ return False
146
+ if not self .t1 :
147
+ return True
148
+ if timestamp > self .t1 :
149
+ return False
150
+ return True
151
+
46
152
__iter__ = iter
47
153
48
154
@property
@@ -51,11 +157,11 @@ def stopped(self):
51
157
52
158
@property
53
159
def duration_delta (self ):
54
- return timedelta (seconds = ( self .t1 or time . time ()) - self . t0 )
160
+ return timedelta (seconds = self .duration )
55
161
56
162
@property
57
163
def duration (self ):
58
- return Duration (self .duration_delta . total_seconds () )
164
+ return Duration (( self .t1 or time . time ()) - self . t0 )
59
165
60
166
@property
61
167
def elapsed_delta (self ):
@@ -88,9 +194,7 @@ def render(self):
88
194
t0 , duration , elapsed , expired , stopped = self .t0 , self .duration , self .elapsed , self .expired , self .stopped
89
195
st = time .strftime ("%T" , time .localtime (t0 ))
90
196
if expired :
91
- duration = "{:0.1f}+{:0.2f}" .format (self .expiration , expired )
92
- else :
93
- duration = "{:0.2f}" .format (duration )
197
+ duration = "{}+{}" .format (self .expiration , expired )
94
198
if stopped :
95
199
et = time .strftime ("%T" , time .localtime (self .t1 ))
96
200
fmt = "{st}..({duration})..{et}"
@@ -106,6 +210,14 @@ def __str__(self):
106
210
def __repr__ (self ):
107
211
return "Timer(%s)" % self .render ()
108
212
213
+ def _repr_pretty_ (self , p , cycle ):
214
+ # used by IPython
215
+ from easypy .colors import MAGENTA , RED
216
+ if cycle :
217
+ p .text ('Timer(...)' )
218
+ return
219
+ p .text ((RED if self .expired else MAGENTA )(self .render ()))
220
+
109
221
110
222
class BackoffTimer (Timer ):
111
223
0 commit comments