Skip to content

Commit 96439fb

Browse files
jbrockmendeljreback
authored andcommitted
centralize and de-privatize month/day name constants (#18728)
1 parent b70b05c commit 96439fb

File tree

11 files changed

+62
-73
lines changed

11 files changed

+62
-73
lines changed

pandas/_libs/tslibs/ccalendar.pyx

+11
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,17 @@ cdef int32_t* _month_offset = [
3333
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365,
3434
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]
3535

36+
# Canonical location for other modules to find name constants
37+
MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
38+
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
39+
MONTH_NUMBERS = {name: num for num, name in enumerate(MONTHS)}
40+
MONTH_ALIASES = {(num + 1): name for num, name in enumerate(MONTHS)}
41+
MONTH_TO_CAL_NUM = {name: num + 1 for num, name in enumerate(MONTHS)}
42+
43+
DAYS = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
44+
int_to_weekday = {num: name for num, name in enumerate(DAYS)}
45+
weekday_to_int = {int_to_weekday[key]: key for key in int_to_weekday}
46+
3647
# ----------------------------------------------------------------------
3748

3849

pandas/_libs/tslibs/fields.pyx

+4-4
Original file line numberDiff line numberDiff line change
@@ -139,8 +139,8 @@ def get_start_end_field(ndarray[int64_t] dtindex, object field,
139139
int mo_off, dom, doy, dow, ldom
140140

141141
_month_offset = np.array(
142-
[[ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ],
143-
[ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ]],
142+
[[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
143+
[0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]],
144144
dtype=np.int32)
145145

146146
count = len(dtindex)
@@ -380,8 +380,8 @@ def get_date_field(ndarray[int64_t] dtindex, object field):
380380
int mo_off, doy, dow
381381

382382
_month_offset = np.array(
383-
[[ 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365 ],
384-
[ 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366 ]],
383+
[[0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365],
384+
[0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]],
385385
dtype=np.int32 )
386386

387387
count = len(dtindex)

pandas/_libs/tslibs/offsets.pyx

+5-22
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ np.import_array()
1717

1818
from util cimport is_string_object, is_integer_object
1919

20+
from ccalendar import MONTHS, DAYS
2021
from conversion cimport tz_convert_single, pydt_to_i8
2122
from frequencies cimport get_freq_code
2223
from nattype cimport NPY_NAT
@@ -27,14 +28,9 @@ from np_datetime cimport (pandas_datetimestruct,
2728
# ---------------------------------------------------------------------
2829
# Constants
2930

30-
# Duplicated in tslib
31-
_MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
32-
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
33-
_int_to_month = {(k + 1): v for k, v in enumerate(_MONTHS)}
34-
_month_to_int = {v: k for k, v in _int_to_month.items()}
35-
3631

3732
class WeekDay(object):
33+
# TODO: Remove: This is not used outside of tests
3834
MON = 0
3935
TUE = 1
4036
WED = 2
@@ -44,18 +40,6 @@ class WeekDay(object):
4440
SUN = 6
4541

4642

47-
_int_to_weekday = {
48-
WeekDay.MON: 'MON',
49-
WeekDay.TUE: 'TUE',
50-
WeekDay.WED: 'WED',
51-
WeekDay.THU: 'THU',
52-
WeekDay.FRI: 'FRI',
53-
WeekDay.SAT: 'SAT',
54-
WeekDay.SUN: 'SUN'}
55-
56-
_weekday_to_int = {_int_to_weekday[key]: key for key in _int_to_weekday}
57-
58-
5943
_offset_to_period_map = {
6044
'WEEKDAY': 'D',
6145
'EOM': 'M',
@@ -88,17 +72,16 @@ _offset_to_period_map = {
8872
need_suffix = ['QS', 'BQ', 'BQS', 'YS', 'AS', 'BY', 'BA', 'BYS', 'BAS']
8973

9074
for __prefix in need_suffix:
91-
for _m in _MONTHS:
75+
for _m in MONTHS:
9276
key = '%s-%s' % (__prefix, _m)
9377
_offset_to_period_map[key] = _offset_to_period_map[__prefix]
9478

9579
for __prefix in ['A', 'Q']:
96-
for _m in _MONTHS:
80+
for _m in MONTHS:
9781
_alias = '%s-%s' % (__prefix, _m)
9882
_offset_to_period_map[_alias] = _alias
9983

100-
_days = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
101-
for _d in _days:
84+
for _d in DAYS:
10285
_offset_to_period_map['W-%s' % _d] = 'W-%s' % _d
10386

10487

pandas/_libs/tslibs/parsing.pyx

+5-8
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,9 @@ from dateutil.relativedelta import relativedelta
4141
from dateutil.parser import DEFAULTPARSER
4242
from dateutil.parser import parse as du_parse
4343

44+
from ccalendar import MONTH_NUMBERS
45+
from nattype import nat_strings
46+
4447
# ----------------------------------------------------------------------
4548
# Constants
4649

@@ -49,14 +52,8 @@ class DateParseError(ValueError):
4952
pass
5053

5154

52-
_nat_strings = set(['NaT', 'nat', 'NAT', 'nan', 'NaN', 'NAN'])
53-
5455
_DEFAULT_DATETIME = datetime(1, 1, 1).replace(hour=0, minute=0,
5556
second=0, microsecond=0)
56-
_MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
57-
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
58-
_MONTH_NUMBERS = {k: i for i, k in enumerate(_MONTHS)}
59-
_MONTH_ALIASES = {(k + 1): v for k, v in enumerate(_MONTHS)}
6057

6158
cdef object _TIMEPAT = re.compile(r'^([01]?[0-9]|2[0-3]):([0-5][0-9])')
6259

@@ -213,7 +210,7 @@ cdef inline object _parse_dateabbr_string(object date_string, object default,
213210
# len(date_string) == 0
214211
# should be NaT???
215212

216-
if date_string in _nat_strings:
213+
if date_string in nat_strings:
217214
return NAT_SENTINEL, NAT_SENTINEL, ''
218215

219216
date_string = date_string.upper()
@@ -267,7 +264,7 @@ cdef inline object _parse_dateabbr_string(object date_string, object default,
267264
if freq is not None:
268265
# hack attack, #1228
269266
try:
270-
mnum = _MONTH_NUMBERS[_get_rule_month(freq)] + 1
267+
mnum = MONTH_NUMBERS[_get_rule_month(freq)] + 1
271268
except (KeyError, ValueError):
272269
msg = ('Unable to retrieve month information from given '
273270
'freq: {0}').format(freq)

pandas/_libs/tslibs/period.pyx

+3-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,9 @@ from timestamps import Timestamp
3232
from timezones cimport is_utc, is_tzlocal, get_utcoffset, get_dst_info
3333
from timedeltas cimport delta_to_nanoseconds
3434

35+
from ccalendar import MONTH_NUMBERS
3536
from parsing import (parse_time_string, NAT_SENTINEL,
36-
_get_rule_month, _MONTH_NUMBERS)
37+
_get_rule_month)
3738
from frequencies cimport get_freq_code
3839
from resolution import resolution, Resolution
3940
from nattype import nat_strings, NaT, iNaT
@@ -1148,7 +1149,7 @@ def _quarter_to_myear(year, quarter, freq):
11481149
if quarter <= 0 or quarter > 4:
11491150
raise ValueError('Quarter must be 1 <= q <= 4')
11501151

1151-
mnum = _MONTH_NUMBERS[_get_rule_month(freq)] + 1
1152+
mnum = MONTH_NUMBERS[_get_rule_month(freq)] + 1
11521153
month = (mnum + (quarter - 1) * 3) % 12 + 1
11531154
if month > mnum:
11541155
year -= 1

pandas/_libs/tslibs/resolution.pyx

+8-15
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ from pandas._libs.khash cimport (khiter_t,
1717

1818
from cpython.datetime cimport datetime
1919

20-
from np_datetime cimport (pandas_datetimestruct,
21-
dtstruct_to_dt64, dt64_to_dtstruct)
20+
from np_datetime cimport pandas_datetimestruct, dt64_to_dtstruct
2221
from frequencies cimport get_freq_code
2322
from timezones cimport (is_utc, is_tzlocal,
2423
maybe_get_tz, get_dst_info, get_utcoffset)
2524
from fields import build_field_sarray
2625
from conversion import tz_convert
26+
from ccalendar import DAYS, MONTH_ALIASES, int_to_weekday
2727

2828
from pandas._libs.properties import cache_readonly
2929
from pandas._libs.tslib import Timestamp
@@ -50,13 +50,6 @@ _ONE_MINUTE = 60 * _ONE_SECOND
5050
_ONE_HOUR = 60 * _ONE_MINUTE
5151
_ONE_DAY = 24 * _ONE_HOUR
5252

53-
DAYS = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
54-
_weekday_rule_aliases = {k: v for k, v in enumerate(DAYS)}
55-
56-
_MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
57-
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
58-
_MONTH_ALIASES = {(k + 1): v for k, v in enumerate(_MONTHS)}
59-
6053
# ----------------------------------------------------------------------
6154

6255
cpdef resolution(ndarray[int64_t] stamps, tz=None):
@@ -354,7 +347,7 @@ class Resolution(object):
354347
# Frequency Inference
355348

356349

357-
# TODO: this is non performiant logic here (and duplicative) and this
350+
# TODO: this is non performant logic here (and duplicative) and this
358351
# simply should call unique_1d directly
359352
# plus no reason to depend on khash directly
360353
cdef unique_deltas(ndarray[int64_t] arr):
@@ -537,15 +530,15 @@ class _FrequencyInferer(object):
537530
annual_rule = self._get_annual_rule()
538531
if annual_rule:
539532
nyears = self.ydiffs[0]
540-
month = _MONTH_ALIASES[self.rep_stamp.month]
533+
month = MONTH_ALIASES[self.rep_stamp.month]
541534
alias = '{prefix}-{month}'.format(prefix=annual_rule, month=month)
542535
return _maybe_add_count(alias, nyears)
543536

544537
quarterly_rule = self._get_quarterly_rule()
545538
if quarterly_rule:
546539
nquarters = self.mdiffs[0] / 3
547540
mod_dict = {0: 12, 2: 11, 1: 10}
548-
month = _MONTH_ALIASES[mod_dict[self.rep_stamp.month % 3]]
541+
month = MONTH_ALIASES[mod_dict[self.rep_stamp.month % 3]]
549542
alias = '{prefix}-{month}'.format(prefix=quarterly_rule,
550543
month=month)
551544
return _maybe_add_count(alias, nquarters)
@@ -558,7 +551,7 @@ class _FrequencyInferer(object):
558551
days = self.deltas[0] / _ONE_DAY
559552
if days % 7 == 0:
560553
# Weekly
561-
day = _weekday_rule_aliases[self.rep_stamp.weekday()]
554+
day = int_to_weekday[self.rep_stamp.weekday()]
562555
return _maybe_add_count('W-{day}'.format(day=day), days / 7)
563556
else:
564557
return _maybe_add_count('D', days)
@@ -630,7 +623,7 @@ class _FrequencyInferer(object):
630623

631624
# get which week
632625
week = week_of_months[0] + 1
633-
wd = _weekday_rule_aliases[weekdays[0]]
626+
wd = int_to_weekday[weekdays[0]]
634627

635628
return 'WOM-{week}{weekday}'.format(week=week, weekday=wd)
636629

@@ -642,7 +635,7 @@ class _TimedeltaFrequencyInferer(_FrequencyInferer):
642635
days = self.deltas[0] / _ONE_DAY
643636
if days % 7 == 0:
644637
# Weekly
645-
wd = _weekday_rule_aliases[self.rep_stamp.weekday()]
638+
wd = int_to_weekday[self.rep_stamp.weekday()]
646639
alias = 'W-{weekday}'.format(weekday=wd)
647640
return _maybe_add_count(alias, days / 7)
648641
else:

pandas/tests/indexes/period/test_tools.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
import pandas.core.indexes.period as period
77
from pandas.compat import lrange
88
from pandas.tseries.frequencies import get_freq
9-
from pandas._libs.tslibs.resolution import _MONTHS as MONTHS
9+
10+
from pandas._libs.tslibs.ccalendar import MONTHS
1011
from pandas._libs.tslibs.period import period_ordinal, period_asfreq
1112
from pandas import (PeriodIndex, Period, DatetimeIndex, Timestamp, Series,
1213
date_range, to_datetime, period_range)

pandas/tests/scalar/test_period.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@
1212

1313
from pandas._libs import tslib
1414
from pandas._libs.tslibs import period as libperiod
15+
from pandas._libs.tslibs.ccalendar import DAYS, MONTHS
1516
from pandas._libs.tslibs.parsing import DateParseError
1617
from pandas import Period, Timestamp, offsets
17-
from pandas._libs.tslibs.resolution import DAYS, _MONTHS as MONTHS
1818

1919

2020
class TestPeriodProperties(object):

pandas/tests/test_resample.py

+2-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@
2222
from pandas.core.base import SpecificationError, AbstractMethodError
2323
from pandas.errors import UnsupportedFunctionCall
2424
from pandas.core.groupby import DataError
25-
from pandas._libs.tslibs.resolution import DAYS, _MONTHS as MONTHS
25+
2626
from pandas.tseries.frequencies import to_offset
2727
from pandas.core.indexes.datetimes import date_range
2828
from pandas.tseries.offsets import Minute, BDay
@@ -33,6 +33,7 @@
3333
from pandas.util.testing import (assert_series_equal, assert_almost_equal,
3434
assert_frame_equal, assert_index_equal)
3535
from pandas._libs.tslibs.period import IncompatibleFrequency
36+
from pandas._libs.tslibs.ccalendar import DAYS, MONTHS
3637

3738
bday = BDay()
3839

pandas/tseries/frequencies.py

+4-3
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,8 @@
2525
from pandas._libs.tslibs.resolution import (Resolution,
2626
_FrequencyInferer,
2727
_TimedeltaFrequencyInferer)
28-
from pandas._libs.tslibs.parsing import _get_rule_month, _MONTH_NUMBERS
28+
from pandas._libs.tslibs.parsing import _get_rule_month
29+
from pandas._libs.tslibs.ccalendar import MONTH_NUMBERS
2930

3031
from pytz import AmbiguousTimeError
3132

@@ -496,8 +497,8 @@ def _is_annual(rule):
496497

497498

498499
def _quarter_months_conform(source, target):
499-
snum = _MONTH_NUMBERS[source]
500-
tnum = _MONTH_NUMBERS[target]
500+
snum = MONTH_NUMBERS[source]
501+
tnum = MONTH_NUMBERS[target]
501502
return snum % 3 == tnum % 3
502503

503504

0 commit comments

Comments
 (0)