Skip to content

centralize and de-privatize month/day name constants #18728

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Dec 12, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 11 additions & 0 deletions pandas/_libs/tslibs/ccalendar.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,17 @@ cdef int32_t* _month_offset = [
0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334, 365,
0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335, 366]

# Canonical location for other modules to find name constants
MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
MONTH_NUMBERS = {name: num for num, name in enumerate(MONTHS)}
MONTH_ALIASES = {(num + 1): name for num, name in enumerate(MONTHS)}
MONTH_TO_CAL_NUM = {name: num + 1 for num, name in enumerate(MONTHS)}

DAYS = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
int_to_weekday = {num: name for num, name in enumerate(DAYS)}
weekday_to_int = {int_to_weekday[key]: key for key in int_to_weekday}

# ----------------------------------------------------------------------


Expand Down
8 changes: 4 additions & 4 deletions pandas/_libs/tslibs/fields.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ def get_start_end_field(ndarray[int64_t] dtindex, object field,
int mo_off, dom, doy, dow, ldom

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

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

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

count = len(dtindex)
Expand Down
27 changes: 5 additions & 22 deletions pandas/_libs/tslibs/offsets.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ np.import_array()

from util cimport is_string_object, is_integer_object

from ccalendar import MONTHS, DAYS
from conversion cimport tz_convert_single, pydt_to_i8
from frequencies cimport get_freq_code
from nattype cimport NPY_NAT
Expand All @@ -27,14 +28,9 @@ from np_datetime cimport (pandas_datetimestruct,
# ---------------------------------------------------------------------
# Constants

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


class WeekDay(object):
# TODO: Remove: This is not used outside of tests
MON = 0
TUE = 1
WED = 2
Expand All @@ -44,18 +40,6 @@ class WeekDay(object):
SUN = 6


_int_to_weekday = {
WeekDay.MON: 'MON',
WeekDay.TUE: 'TUE',
WeekDay.WED: 'WED',
WeekDay.THU: 'THU',
WeekDay.FRI: 'FRI',
WeekDay.SAT: 'SAT',
WeekDay.SUN: 'SUN'}

_weekday_to_int = {_int_to_weekday[key]: key for key in _int_to_weekday}


_offset_to_period_map = {
'WEEKDAY': 'D',
'EOM': 'M',
Expand Down Expand Up @@ -88,17 +72,16 @@ _offset_to_period_map = {
need_suffix = ['QS', 'BQ', 'BQS', 'YS', 'AS', 'BY', 'BA', 'BYS', 'BAS']

for __prefix in need_suffix:
for _m in _MONTHS:
for _m in MONTHS:
key = '%s-%s' % (__prefix, _m)
_offset_to_period_map[key] = _offset_to_period_map[__prefix]

for __prefix in ['A', 'Q']:
for _m in _MONTHS:
for _m in MONTHS:
_alias = '%s-%s' % (__prefix, _m)
_offset_to_period_map[_alias] = _alias

_days = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
for _d in _days:
for _d in DAYS:
_offset_to_period_map['W-%s' % _d] = 'W-%s' % _d


Expand Down
13 changes: 5 additions & 8 deletions pandas/_libs/tslibs/parsing.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ from dateutil.relativedelta import relativedelta
from dateutil.parser import DEFAULTPARSER
from dateutil.parser import parse as du_parse

from ccalendar import MONTH_NUMBERS
from nattype import nat_strings

# ----------------------------------------------------------------------
# Constants

Expand All @@ -49,14 +52,8 @@ class DateParseError(ValueError):
pass


_nat_strings = set(['NaT', 'nat', 'NAT', 'nan', 'NaN', 'NAN'])

_DEFAULT_DATETIME = datetime(1, 1, 1).replace(hour=0, minute=0,
second=0, microsecond=0)
_MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
_MONTH_NUMBERS = {k: i for i, k in enumerate(_MONTHS)}
_MONTH_ALIASES = {(k + 1): v for k, v in enumerate(_MONTHS)}

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

Expand Down Expand Up @@ -213,7 +210,7 @@ cdef inline object _parse_dateabbr_string(object date_string, object default,
# len(date_string) == 0
# should be NaT???

if date_string in _nat_strings:
if date_string in nat_strings:
return NAT_SENTINEL, NAT_SENTINEL, ''

date_string = date_string.upper()
Expand Down Expand Up @@ -267,7 +264,7 @@ cdef inline object _parse_dateabbr_string(object date_string, object default,
if freq is not None:
# hack attack, #1228
try:
mnum = _MONTH_NUMBERS[_get_rule_month(freq)] + 1
mnum = MONTH_NUMBERS[_get_rule_month(freq)] + 1
except (KeyError, ValueError):
msg = ('Unable to retrieve month information from given '
'freq: {0}').format(freq)
Expand Down
5 changes: 3 additions & 2 deletions pandas/_libs/tslibs/period.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,9 @@ from timestamps import Timestamp
from timezones cimport is_utc, is_tzlocal, get_utcoffset, get_dst_info
from timedeltas cimport delta_to_nanoseconds

from ccalendar import MONTH_NUMBERS
from parsing import (parse_time_string, NAT_SENTINEL,
_get_rule_month, _MONTH_NUMBERS)
_get_rule_month)
from frequencies cimport get_freq_code
from resolution import resolution, Resolution
from nattype import nat_strings, NaT, iNaT
Expand Down Expand Up @@ -1148,7 +1149,7 @@ def _quarter_to_myear(year, quarter, freq):
if quarter <= 0 or quarter > 4:
raise ValueError('Quarter must be 1 <= q <= 4')

mnum = _MONTH_NUMBERS[_get_rule_month(freq)] + 1
mnum = MONTH_NUMBERS[_get_rule_month(freq)] + 1
month = (mnum + (quarter - 1) * 3) % 12 + 1
if month > mnum:
year -= 1
Expand Down
23 changes: 8 additions & 15 deletions pandas/_libs/tslibs/resolution.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,13 @@ from pandas._libs.khash cimport (khiter_t,

from cpython.datetime cimport datetime

from np_datetime cimport (pandas_datetimestruct,
dtstruct_to_dt64, dt64_to_dtstruct)
from np_datetime cimport pandas_datetimestruct, dt64_to_dtstruct
from frequencies cimport get_freq_code
from timezones cimport (is_utc, is_tzlocal,
maybe_get_tz, get_dst_info, get_utcoffset)
from fields import build_field_sarray
from conversion import tz_convert
from ccalendar import DAYS, MONTH_ALIASES, int_to_weekday

from pandas._libs.properties import cache_readonly
from pandas._libs.tslib import Timestamp
Expand All @@ -50,13 +50,6 @@ _ONE_MINUTE = 60 * _ONE_SECOND
_ONE_HOUR = 60 * _ONE_MINUTE
_ONE_DAY = 24 * _ONE_HOUR

DAYS = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
_weekday_rule_aliases = {k: v for k, v in enumerate(DAYS)}

_MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
_MONTH_ALIASES = {(k + 1): v for k, v in enumerate(_MONTHS)}

# ----------------------------------------------------------------------

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


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

quarterly_rule = self._get_quarterly_rule()
if quarterly_rule:
nquarters = self.mdiffs[0] / 3
mod_dict = {0: 12, 2: 11, 1: 10}
month = _MONTH_ALIASES[mod_dict[self.rep_stamp.month % 3]]
month = MONTH_ALIASES[mod_dict[self.rep_stamp.month % 3]]
alias = '{prefix}-{month}'.format(prefix=quarterly_rule,
month=month)
return _maybe_add_count(alias, nquarters)
Expand All @@ -558,7 +551,7 @@ class _FrequencyInferer(object):
days = self.deltas[0] / _ONE_DAY
if days % 7 == 0:
# Weekly
day = _weekday_rule_aliases[self.rep_stamp.weekday()]
day = int_to_weekday[self.rep_stamp.weekday()]
return _maybe_add_count('W-{day}'.format(day=day), days / 7)
else:
return _maybe_add_count('D', days)
Expand Down Expand Up @@ -630,7 +623,7 @@ class _FrequencyInferer(object):

# get which week
week = week_of_months[0] + 1
wd = _weekday_rule_aliases[weekdays[0]]
wd = int_to_weekday[weekdays[0]]

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

Expand All @@ -642,7 +635,7 @@ class _TimedeltaFrequencyInferer(_FrequencyInferer):
days = self.deltas[0] / _ONE_DAY
if days % 7 == 0:
# Weekly
wd = _weekday_rule_aliases[self.rep_stamp.weekday()]
wd = int_to_weekday[self.rep_stamp.weekday()]
alias = 'W-{weekday}'.format(weekday=wd)
return _maybe_add_count(alias, days / 7)
else:
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/indexes/period/test_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
import pandas.core.indexes.period as period
from pandas.compat import lrange
from pandas.tseries.frequencies import get_freq
from pandas._libs.tslibs.resolution import _MONTHS as MONTHS

from pandas._libs.tslibs.ccalendar import MONTHS
from pandas._libs.tslibs.period import period_ordinal, period_asfreq
from pandas import (PeriodIndex, Period, DatetimeIndex, Timestamp, Series,
date_range, to_datetime, period_range)
Expand Down
2 changes: 1 addition & 1 deletion pandas/tests/scalar/test_period.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@

from pandas._libs import tslib
from pandas._libs.tslibs import period as libperiod
from pandas._libs.tslibs.ccalendar import DAYS, MONTHS
from pandas._libs.tslibs.parsing import DateParseError
from pandas import Period, Timestamp, offsets
from pandas._libs.tslibs.resolution import DAYS, _MONTHS as MONTHS


class TestPeriodProperties(object):
Expand Down
3 changes: 2 additions & 1 deletion pandas/tests/test_resample.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
from pandas.core.base import SpecificationError, AbstractMethodError
from pandas.errors import UnsupportedFunctionCall
from pandas.core.groupby import DataError
from pandas._libs.tslibs.resolution import DAYS, _MONTHS as MONTHS

from pandas.tseries.frequencies import to_offset
from pandas.core.indexes.datetimes import date_range
from pandas.tseries.offsets import Minute, BDay
Expand All @@ -33,6 +33,7 @@
from pandas.util.testing import (assert_series_equal, assert_almost_equal,
assert_frame_equal, assert_index_equal)
from pandas._libs.tslibs.period import IncompatibleFrequency
from pandas._libs.tslibs.ccalendar import DAYS, MONTHS

bday = BDay()

Expand Down
7 changes: 4 additions & 3 deletions pandas/tseries/frequencies.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@
from pandas._libs.tslibs.resolution import (Resolution,
_FrequencyInferer,
_TimedeltaFrequencyInferer)
from pandas._libs.tslibs.parsing import _get_rule_month, _MONTH_NUMBERS
from pandas._libs.tslibs.parsing import _get_rule_month
from pandas._libs.tslibs.ccalendar import MONTH_NUMBERS

from pytz import AmbiguousTimeError

Expand Down Expand Up @@ -496,8 +497,8 @@ def _is_annual(rule):


def _quarter_months_conform(source, target):
snum = _MONTH_NUMBERS[source]
tnum = _MONTH_NUMBERS[target]
snum = MONTH_NUMBERS[source]
tnum = MONTH_NUMBERS[target]
return snum % 3 == tnum % 3


Expand Down
Loading