1
+ from enum import Enum
2
+
1
3
import numpy as np
2
4
from numpy cimport ndarray, int64_t, int32_t
3
5
@@ -25,10 +27,46 @@ cdef:
25
27
int RESO_HR = 5
26
28
int RESO_DAY = 6
27
29
30
+ reso_str_bump_map = {
31
+ " D" : " H" ,
32
+ " H" : " T" ,
33
+ " T" : " S" ,
34
+ " S" : " L" ,
35
+ " L" : " U" ,
36
+ " U" : " N" ,
37
+ " N" : None ,
38
+ }
39
+
40
+ _abbrev_to_attrnames = {v: k for k, v in attrname_to_abbrevs.items()}
41
+
42
+ _reso_str_map = {
43
+ RESO_NS: " nanosecond" ,
44
+ RESO_US: " microsecond" ,
45
+ RESO_MS: " millisecond" ,
46
+ RESO_SEC: " second" ,
47
+ RESO_MIN: " minute" ,
48
+ RESO_HR: " hour" ,
49
+ RESO_DAY: " day" ,
50
+ }
51
+
52
+ _str_reso_map = {v: k for k, v in _reso_str_map.items()}
53
+
54
+ # factor to multiply a value by to convert it to the next finer grained
55
+ # resolution
56
+ _reso_mult_map = {
57
+ RESO_NS: None ,
58
+ RESO_US: 1000 ,
59
+ RESO_MS: 1000 ,
60
+ RESO_SEC: 1000 ,
61
+ RESO_MIN: 60 ,
62
+ RESO_HR: 60 ,
63
+ RESO_DAY: 24 ,
64
+ }
28
65
29
66
# ----------------------------------------------------------------------
30
67
31
- def resolution (const int64_t[:] stamps , tz = None ):
68
+
69
+ def get_resolution (const int64_t[:] stamps , tz = None ):
32
70
cdef:
33
71
Py_ssize_t i, n = len (stamps)
34
72
npy_datetimestruct dts
@@ -82,7 +120,7 @@ def resolution(const int64_t[:] stamps, tz=None):
82
120
if curr_reso < reso:
83
121
reso = curr_reso
84
122
85
- return reso
123
+ return Resolution( reso)
86
124
87
125
88
126
cdef inline int _reso_stamp(npy_datetimestruct * dts):
@@ -99,7 +137,7 @@ cdef inline int _reso_stamp(npy_datetimestruct *dts):
99
137
return RESO_DAY
100
138
101
139
102
- class Resolution :
140
+ class Resolution ( Enum ) :
103
141
104
142
# Note: cython won't allow us to reference the cdef versions at the
105
143
# module level
@@ -111,41 +149,14 @@ class Resolution:
111
149
RESO_HR = 5
112
150
RESO_DAY = 6
113
151
114
- _reso_str_map = {
115
- RESO_NS: ' nanosecond' ,
116
- RESO_US: ' microsecond' ,
117
- RESO_MS: ' millisecond' ,
118
- RESO_SEC: ' second' ,
119
- RESO_MIN: ' minute' ,
120
- RESO_HR: ' hour' ,
121
- RESO_DAY: ' day' }
122
-
123
- # factor to multiply a value by to convert it to the next finer grained
124
- # resolution
125
- _reso_mult_map = {
126
- RESO_NS: None ,
127
- RESO_US: 1000 ,
128
- RESO_MS: 1000 ,
129
- RESO_SEC: 1000 ,
130
- RESO_MIN: 60 ,
131
- RESO_HR: 60 ,
132
- RESO_DAY: 24 }
133
-
134
- reso_str_bump_map = {
135
- ' D' : ' H' ,
136
- ' H' : ' T' ,
137
- ' T' : ' S' ,
138
- ' S' : ' L' ,
139
- ' L' : ' U' ,
140
- ' U' : ' N' ,
141
- ' N' : None }
142
-
143
- _str_reso_map = {v: k for k, v in _reso_str_map.items()}
144
-
145
- _freq_reso_map = {v: k for k, v in attrname_to_abbrevs.items()}
152
+ def __lt__ (self , other ):
153
+ return self .value < other.value
154
+
155
+ def __ge__ (self , other ):
156
+ return self .value >= other.value
146
157
147
158
@classmethod
148
- def get_str (cls , reso: int ) -> str:
159
+ def get_str (cls , reso: "Resolution" ) -> str:
149
160
"""
150
161
Return resolution str against resolution code.
151
162
@@ -154,10 +165,10 @@ class Resolution:
154
165
>>> Resolution.get_str(Resolution.RESO_SEC )
155
166
'second'
156
167
"""
157
- return cls. _reso_str_map.get( reso , 'day')
168
+ return _reso_str_map[ reso.value]
158
169
159
170
@classmethod
160
- def get_reso(cls , resostr: str ) -> int :
171
+ def get_reso(cls , resostr: str ) -> "Resolution" :
161
172
"""
162
173
Return resolution str against resolution code.
163
174
@@ -169,25 +180,27 @@ class Resolution:
169
180
>>> Resolution.get_reso('second') == Resolution.RESO_SEC
170
181
True
171
182
"""
172
- return cls._str_reso_map.get( resostr , cls. RESO_DAY )
183
+ return cls(_str_reso_map[ resostr] )
173
184
174
185
@classmethod
175
- def get_str_from_freq (cls , freq: str ) -> str:
186
+ def get_attrname_from_abbrev (cls , freq: str ) -> str:
176
187
"""
177
188
Return resolution str against frequency str.
178
189
179
190
Examples
180
191
--------
181
- >>> Resolution.get_str_from_freq ('H')
192
+ >>> Resolution.get_attrname_from_abbrev ('H')
182
193
'hour'
183
194
"""
184
- return cls._freq_reso_map.get( freq , 'day')
195
+ return _abbrev_to_attrnames[ freq]
185
196
186
197
@classmethod
187
- def get_reso_from_freq(cls , freq: str ) -> int :
198
+ def get_reso_from_freq(cls , freq: str ) -> "Resolution" :
188
199
"""
189
200
Return resolution code against frequency str.
190
201
202
+ `freq` is given by the `offset.freqstr` for some DateOffset object.
203
+
191
204
Examples
192
205
--------
193
206
>>> Resolution.get_reso_from_freq('H')
@@ -196,16 +209,16 @@ class Resolution:
196
209
>>> Resolution.get_reso_from_freq('H') == Resolution.RESO_HR
197
210
True
198
211
"""
199
- return cls.get_reso(cls.get_str_from_freq (freq ))
212
+ return cls.get_reso(cls.get_attrname_from_abbrev (freq ))
200
213
201
214
@classmethod
202
- def get_stride_from_decimal(cls , value , freq ):
215
+ def get_stride_from_decimal(cls , value: float , freq: str ):
203
216
"""
204
217
Convert freq with decimal stride into a higher freq with integer stride
205
218
206
219
Parameters
207
220
----------
208
- value : int or float
221
+ value : float
209
222
freq : str
210
223
Frequency string
211
224
@@ -229,13 +242,13 @@ class Resolution:
229
242
return int (value), freq
230
243
else :
231
244
start_reso = cls .get_reso_from_freq(freq)
232
- if start_reso == 0 :
245
+ if start_reso.value == 0 :
233
246
raise ValueError (
234
247
" Could not convert to integer offset at any resolution"
235
248
)
236
249
237
- next_value = cls . _reso_mult_map[start_reso] * value
238
- next_name = cls . reso_str_bump_map[freq]
250
+ next_value = _reso_mult_map[start_reso.value ] * value
251
+ next_name = reso_str_bump_map[freq]
239
252
return cls .get_stride_from_decimal(next_value, next_name)
240
253
241
254
0 commit comments