11# period frequency constants corresponding to scikits timeseries
22# originals
3+ from enum import Enum
34
45
56cdef class PeriodDtypeBase:
@@ -112,6 +113,9 @@ _period_code_map.update({
112113 " C" : 5000 , # Custom Business Day
113114})
114115
116+ cdef set _month_names = {
117+ x.split(" -" )[- 1 ] for x in _period_code_map.keys() if x.startswith(" A-" )
118+ }
115119
116120# Map attribute-name resolutions to resolution abbreviations
117121_attrname_to_abbrevs = {
@@ -127,6 +131,7 @@ _attrname_to_abbrevs = {
127131 " nanosecond" : " N" ,
128132}
129133cdef dict attrname_to_abbrevs = _attrname_to_abbrevs
134+ cdef dict _abbrev_to_attrnames = {v: k for k, v in attrname_to_abbrevs.items()}
130135
131136
132137class FreqGroup :
@@ -149,3 +154,124 @@ class FreqGroup:
149154 def get_freq_group (code: int ) -> int:
150155 # See also: PeriodDtypeBase.freq_group
151156 return (code // 1000) * 1000
157+
158+
159+ class Resolution(Enum ):
160+
161+ # Note: cython won't allow us to reference the cdef versions at the
162+ # module level
163+ RESO_NS = 0
164+ RESO_US = 1
165+ RESO_MS = 2
166+ RESO_SEC = 3
167+ RESO_MIN = 4
168+ RESO_HR = 5
169+ RESO_DAY = 6
170+ RESO_MTH = 7
171+ RESO_QTR = 8
172+ RESO_YR = 9
173+
174+ def __lt__ (self , other ):
175+ return self .value < other.value
176+
177+ def __ge__ (self , other ):
178+ return self .value >= other.value
179+
180+ @property
181+ def freq_group (self ):
182+ # TODO: annotate as returning FreqGroup once that is an enum
183+ if self == Resolution.RESO_NS:
184+ return FreqGroup.FR_NS
185+ elif self == Resolution.RESO_US:
186+ return FreqGroup.FR_US
187+ elif self == Resolution.RESO_MS:
188+ return FreqGroup.FR_MS
189+ elif self == Resolution.RESO_SEC:
190+ return FreqGroup.FR_SEC
191+ elif self == Resolution.RESO_MIN:
192+ return FreqGroup.FR_MIN
193+ elif self == Resolution.RESO_HR:
194+ return FreqGroup.FR_HR
195+ elif self == Resolution.RESO_DAY:
196+ return FreqGroup.FR_DAY
197+ elif self == Resolution.RESO_MTH:
198+ return FreqGroup.FR_MTH
199+ elif self == Resolution.RESO_QTR:
200+ return FreqGroup.FR_QTR
201+ elif self == Resolution.RESO_YR:
202+ return FreqGroup.FR_ANN
203+ else :
204+ raise ValueError (self )
205+
206+ @property
207+ def attrname (self ) -> str:
208+ """
209+ Return datetime attribute name corresponding to this Resolution.
210+
211+ Examples
212+ --------
213+ >>> Resolution.RESO_SEC.attrname
214+ 'second'
215+ """
216+ return _reso_str_map[self.value]
217+
218+ @classmethod
219+ def from_attrname(cls , attrname: str ) -> "Resolution":
220+ """
221+ Return resolution str against resolution code.
222+
223+ Examples
224+ --------
225+ >>> Resolution.from_attrname('second')
226+ 2
227+
228+ >>> Resolution.from_attrname('second') == Resolution.RESO_SEC
229+ True
230+ """
231+ return cls(_str_reso_map[attrname])
232+
233+ @classmethod
234+ def get_reso_from_freq(cls , freq: str ) -> "Resolution":
235+ """
236+ Return resolution code against frequency str.
237+
238+ `freq` is given by the `offset.freqstr` for some DateOffset object.
239+
240+ Examples
241+ --------
242+ >>> Resolution.get_reso_from_freq('H')
243+ 4
244+
245+ >>> Resolution.get_reso_from_freq('H') == Resolution.RESO_HR
246+ True
247+ """
248+ try:
249+ attr_name = _abbrev_to_attrnames[freq]
250+ except KeyError:
251+ # For quarterly and yearly resolutions , we need to chop off
252+ # a month string.
253+ split_freq = freq.split(" -" )
254+ if len(split_freq ) != 2:
255+ raise
256+ if split_freq[1] not in _month_names:
257+ # i.e. we want e.g. "Q-DEC", not "Q-INVALID"
258+ raise
259+ attr_name = _abbrev_to_attrnames[split_freq[0 ]]
260+
261+ return cls.from_attrname(attr_name )
262+
263+
264+ cdef dict _reso_str_map = {
265+ Resolution.RESO_NS.value: " nanosecond" ,
266+ Resolution.RESO_US.value: " microsecond" ,
267+ Resolution.RESO_MS.value: " millisecond" ,
268+ Resolution.RESO_SEC.value: " second" ,
269+ Resolution.RESO_MIN.value: " minute" ,
270+ Resolution.RESO_HR.value: " hour" ,
271+ Resolution.RESO_DAY.value: " day" ,
272+ Resolution.RESO_MTH.value: " month" ,
273+ Resolution.RESO_QTR.value: " quarter" ,
274+ Resolution.RESO_YR.value: " year" ,
275+ }
276+
277+ cdef dict _str_reso_map = {v: k for k, v in _reso_str_map.items()}
0 commit comments