Skip to content

Commit 1361d9a

Browse files
authored
REF: put Resolution in tslibs.dtypes (#34813)
1 parent 7efbcac commit 1361d9a

File tree

2 files changed

+128
-125
lines changed

2 files changed

+128
-125
lines changed

pandas/_libs/tslibs/dtypes.pyx

+126
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# period frequency constants corresponding to scikits timeseries
22
# originals
3+
from enum import Enum
34

45

56
cdef 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
}
129133
cdef 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

132137
class 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()}

pandas/_libs/tslibs/resolution.pyx

+2-125
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,15 @@
1-
from enum import Enum
21

32
import numpy as np
43
from numpy cimport ndarray, int64_t, int32_t
54

65
from pandas._libs.tslibs.util cimport get_nat
76

8-
from pandas._libs.tslibs.dtypes cimport attrname_to_abbrevs
7+
from pandas._libs.tslibs.dtypes import Resolution
98
from pandas._libs.tslibs.np_datetime cimport (
109
npy_datetimestruct, dt64_to_dtstruct)
11-
from pandas._libs.tslibs.frequencies import FreqGroup
1210
from pandas._libs.tslibs.timezones cimport (
1311
is_utc, is_tzlocal, maybe_get_tz, get_dst_info)
14-
from pandas._libs.tslibs.ccalendar cimport get_days_in_month, c_MONTH_NUMBERS
12+
from pandas._libs.tslibs.ccalendar cimport get_days_in_month
1513
from pandas._libs.tslibs.tzconversion cimport tz_convert_utc_to_tzlocal
1614

1715
# ----------------------------------------------------------------------
@@ -31,22 +29,6 @@ cdef:
3129
int RESO_QTR = 8
3230
int RESO_YR = 9
3331

34-
_abbrev_to_attrnames = {v: k for k, v in attrname_to_abbrevs.items()}
35-
36-
_reso_str_map = {
37-
RESO_NS: "nanosecond",
38-
RESO_US: "microsecond",
39-
RESO_MS: "millisecond",
40-
RESO_SEC: "second",
41-
RESO_MIN: "minute",
42-
RESO_HR: "hour",
43-
RESO_DAY: "day",
44-
RESO_MTH: "month",
45-
RESO_QTR: "quarter",
46-
RESO_YR: "year",
47-
}
48-
49-
_str_reso_map = {v: k for k, v in _reso_str_map.items()}
5032

5133
# ----------------------------------------------------------------------
5234

@@ -122,111 +104,6 @@ cdef inline int _reso_stamp(npy_datetimestruct *dts):
122104
return RESO_DAY
123105

124106

125-
class Resolution(Enum):
126-
127-
# Note: cython won't allow us to reference the cdef versions at the
128-
# module level
129-
RESO_NS = 0
130-
RESO_US = 1
131-
RESO_MS = 2
132-
RESO_SEC = 3
133-
RESO_MIN = 4
134-
RESO_HR = 5
135-
RESO_DAY = 6
136-
RESO_MTH = 7
137-
RESO_QTR = 8
138-
RESO_YR = 9
139-
140-
def __lt__(self, other):
141-
return self.value < other.value
142-
143-
def __ge__(self, other):
144-
return self.value >= other.value
145-
146-
@property
147-
def freq_group(self):
148-
# TODO: annotate as returning FreqGroup once that is an enum
149-
if self == Resolution.RESO_NS:
150-
return FreqGroup.FR_NS
151-
elif self == Resolution.RESO_US:
152-
return FreqGroup.FR_US
153-
elif self == Resolution.RESO_MS:
154-
return FreqGroup.FR_MS
155-
elif self == Resolution.RESO_SEC:
156-
return FreqGroup.FR_SEC
157-
elif self == Resolution.RESO_MIN:
158-
return FreqGroup.FR_MIN
159-
elif self == Resolution.RESO_HR:
160-
return FreqGroup.FR_HR
161-
elif self == Resolution.RESO_DAY:
162-
return FreqGroup.FR_DAY
163-
elif self == Resolution.RESO_MTH:
164-
return FreqGroup.FR_MTH
165-
elif self == Resolution.RESO_QTR:
166-
return FreqGroup.FR_QTR
167-
elif self == Resolution.RESO_YR:
168-
return FreqGroup.FR_ANN
169-
else:
170-
raise ValueError(self)
171-
172-
@property
173-
def attrname(self) -> str:
174-
"""
175-
Return datetime attribute name corresponding to this Resolution.
176-
177-
Examples
178-
--------
179-
>>> Resolution.RESO_SEC.attrname
180-
'second'
181-
"""
182-
return _reso_str_map[self.value]
183-
184-
@classmethod
185-
def from_attrname(cls, attrname: str) -> "Resolution":
186-
"""
187-
Return resolution str against resolution code.
188-
189-
Examples
190-
--------
191-
>>> Resolution.from_attrname('second')
192-
2
193-
194-
>>> Resolution.from_attrname('second') == Resolution.RESO_SEC
195-
True
196-
"""
197-
return cls(_str_reso_map[attrname])
198-
199-
@classmethod
200-
def get_reso_from_freq(cls, freq: str) -> "Resolution":
201-
"""
202-
Return resolution code against frequency str.
203-
204-
`freq` is given by the `offset.freqstr` for some DateOffset object.
205-
206-
Examples
207-
--------
208-
>>> Resolution.get_reso_from_freq('H')
209-
4
210-
211-
>>> Resolution.get_reso_from_freq('H') == Resolution.RESO_HR
212-
True
213-
"""
214-
try:
215-
attr_name = _abbrev_to_attrnames[freq]
216-
except KeyError:
217-
# For quarterly and yearly resolutions, we need to chop off
218-
# a month string.
219-
split_freq = freq.split("-")
220-
if len(split_freq) != 2:
221-
raise
222-
if split_freq[1] not in c_MONTH_NUMBERS:
223-
# i.e. we want e.g. "Q-DEC", not "Q-INVALID"
224-
raise
225-
attr_name = _abbrev_to_attrnames[split_freq[0]]
226-
227-
return cls.from_attrname(attr_name)
228-
229-
230107
# ----------------------------------------------------------------------
231108
# Frequency Inference
232109

0 commit comments

Comments
 (0)