1+ from enum import Enum
2+
13import numpy as np
24from numpy cimport ndarray, int64_t, int32_t
35
@@ -25,10 +27,46 @@ cdef:
2527 int RESO_HR = 5
2628 int RESO_DAY = 6
2729
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+ }
2865
2966# ----------------------------------------------------------------------
3067
31- def resolution (const int64_t[:] stamps , tz = None ):
68+
69+ def get_resolution (const int64_t[:] stamps , tz = None ):
3270 cdef:
3371 Py_ssize_t i, n = len (stamps)
3472 npy_datetimestruct dts
@@ -82,7 +120,7 @@ def resolution(const int64_t[:] stamps, tz=None):
82120 if curr_reso < reso:
83121 reso = curr_reso
84122
85- return reso
123+ return Resolution( reso)
86124
87125
88126cdef inline int _reso_stamp(npy_datetimestruct * dts):
@@ -99,7 +137,7 @@ cdef inline int _reso_stamp(npy_datetimestruct *dts):
99137 return RESO_DAY
100138
101139
102- class Resolution :
140+ class Resolution ( Enum ) :
103141
104142 # Note: cython won't allow us to reference the cdef versions at the
105143 # module level
@@ -111,41 +149,14 @@ class Resolution:
111149 RESO_HR = 5
112150 RESO_DAY = 6
113151
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
146157
147158 @classmethod
148- def get_str (cls , reso: int ) -> str:
159+ def get_str (cls , reso: "Resolution" ) -> str:
149160 """
150161 Return resolution str against resolution code.
151162
@@ -154,10 +165,10 @@ class Resolution:
154165 >>> Resolution.get_str(Resolution.RESO_SEC )
155166 'second'
156167 """
157- return cls. _reso_str_map.get( reso , 'day')
168+ return _reso_str_map[ reso.value]
158169
159170 @classmethod
160- def get_reso(cls , resostr: str ) -> int :
171+ def get_reso(cls , resostr: str ) -> "Resolution" :
161172 """
162173 Return resolution str against resolution code.
163174
@@ -169,25 +180,27 @@ class Resolution:
169180 >>> Resolution.get_reso('second') == Resolution.RESO_SEC
170181 True
171182 """
172- return cls._str_reso_map.get( resostr , cls. RESO_DAY )
183+ return cls(_str_reso_map[ resostr] )
173184
174185 @classmethod
175- def get_str_from_freq (cls , freq: str ) -> str:
186+ def get_attrname_from_abbrev (cls , freq: str ) -> str:
176187 """
177188 Return resolution str against frequency str.
178189
179190 Examples
180191 --------
181- >>> Resolution.get_str_from_freq ('H')
192+ >>> Resolution.get_attrname_from_abbrev ('H')
182193 'hour'
183194 """
184- return cls._freq_reso_map.get( freq , 'day')
195+ return _abbrev_to_attrnames[ freq]
185196
186197 @classmethod
187- def get_reso_from_freq(cls , freq: str ) -> int :
198+ def get_reso_from_freq(cls , freq: str ) -> "Resolution" :
188199 """
189200 Return resolution code against frequency str.
190201
202+ `freq` is given by the `offset.freqstr` for some DateOffset object.
203+
191204 Examples
192205 --------
193206 >>> Resolution.get_reso_from_freq('H')
@@ -196,16 +209,16 @@ class Resolution:
196209 >>> Resolution.get_reso_from_freq('H') == Resolution.RESO_HR
197210 True
198211 """
199- return cls.get_reso(cls.get_str_from_freq (freq ))
212+ return cls.get_reso(cls.get_attrname_from_abbrev (freq ))
200213
201214 @classmethod
202- def get_stride_from_decimal(cls , value , freq ):
215+ def get_stride_from_decimal(cls , value: float , freq: str ):
203216 """
204217 Convert freq with decimal stride into a higher freq with integer stride
205218
206219 Parameters
207220 ----------
208- value : int or float
221+ value : float
209222 freq : str
210223 Frequency string
211224
@@ -229,13 +242,13 @@ class Resolution:
229242 return int (value), freq
230243 else :
231244 start_reso = cls .get_reso_from_freq(freq)
232- if start_reso == 0 :
245+ if start_reso.value == 0 :
233246 raise ValueError (
234247 " Could not convert to integer offset at any resolution"
235248 )
236249
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]
239252 return cls .get_stride_from_decimal(next_value, next_name)
240253
241254
0 commit comments