-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
ENH: Return locale based month_name and weekday_name values (#12805, #12806) #18164
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -12,6 +12,8 @@ cimport numpy as cnp | |
from numpy cimport int64_t, int32_t | ||
cnp.import_array() | ||
|
||
from locale import LC_TIME | ||
from strptime import LocaleTime | ||
|
||
# ---------------------------------------------------------------------- | ||
# Constants | ||
|
@@ -35,11 +37,18 @@ cdef int32_t* _month_offset = [ | |
# Canonical location for other modules to find name constants | ||
MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', | ||
'AUG', 'SEP', 'OCT', 'NOV', 'DEC'] | ||
# The first blank line is consistent with calendar.month_name in the calendar | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. really? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. (Unfortunately) yes.
|
||
# standard library | ||
MONTHS_FULL = ['', 'January', 'February', 'March', 'April', 'May', 'June', | ||
'July', 'August', 'September', 'October', 'November', | ||
'December'] | ||
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'] | ||
DAYS_FULL = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', | ||
'Saturday', 'Sunday'] | ||
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} | ||
|
||
|
@@ -199,3 +208,23 @@ cpdef int32_t get_day_of_year(int year, int month, int day) nogil: | |
|
||
day_of_year = mo_off + day | ||
return day_of_year | ||
|
||
|
||
cpdef get_locale_names(object name_type, object locale=None): | ||
"""Returns an array of localized day or month names | ||
|
||
Parameters | ||
---------- | ||
name_type : string, attribute of LocaleTime() in which to return localized | ||
names | ||
locale : string | ||
|
||
Returns | ||
------- | ||
list of locale names | ||
|
||
""" | ||
from pandas.util.testing import set_locale | ||
|
||
with set_locale(locale, LC_TIME): | ||
return getattr(LocaleTime(), name_type) |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -13,7 +13,7 @@ cimport numpy as cnp | |
from numpy cimport ndarray, int64_t, int32_t, int8_t | ||
cnp.import_array() | ||
|
||
|
||
from ccalendar import get_locale_names, MONTHS_FULL, DAYS_FULL | ||
from ccalendar cimport (get_days_in_month, is_leapyear, dayofweek, | ||
get_week_of_year, get_day_of_year) | ||
from np_datetime cimport (pandas_datetimestruct, pandas_timedeltastruct, | ||
|
@@ -85,34 +85,49 @@ def build_field_sarray(ndarray[int64_t] dtindex): | |
|
||
@cython.wraparound(False) | ||
@cython.boundscheck(False) | ||
def get_date_name_field(ndarray[int64_t] dtindex, object field): | ||
def get_date_name_field(ndarray[int64_t] dtindex, object field, | ||
object locale=None): | ||
""" | ||
Given a int64-based datetime index, return array of strings of date | ||
name based on requested field (e.g. weekday_name) | ||
""" | ||
cdef: | ||
Py_ssize_t i, count = 0 | ||
ndarray[object] out | ||
ndarray[object] out, names | ||
pandas_datetimestruct dts | ||
int dow | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. instead of using _dayname, _monthname, use |
||
_dayname = np.array( | ||
['Monday', 'Tuesday', 'Wednesday', 'Thursday', | ||
'Friday', 'Saturday', 'Sunday'], | ||
dtype=np.object_) | ||
|
||
count = len(dtindex) | ||
out = np.empty(count, dtype=object) | ||
|
||
if field == 'weekday_name': | ||
if field == 'day_name' or field == 'weekday_name': | ||
if locale is None: | ||
names = np.array(DAYS_FULL, dtype=np.object_) | ||
else: | ||
names = np.array(get_locale_names('f_weekday', locale), | ||
dtype=np.object_) | ||
for i in range(count): | ||
if dtindex[i] == NPY_NAT: | ||
out[i] = np.nan | ||
continue | ||
|
||
dt64_to_dtstruct(dtindex[i], &dts) | ||
dow = dayofweek(dts.year, dts.month, dts.day) | ||
out[i] = _dayname[dow] | ||
out[i] = names[dow].capitalize() | ||
return out | ||
elif field == 'month_name': | ||
if locale is None: | ||
names = np.array(MONTHS_FULL, dtype=np.object_) | ||
else: | ||
names = np.array(get_locale_names('f_month', locale), | ||
dtype=np.object_) | ||
for i in range(count): | ||
if dtindex[i] == NPY_NAT: | ||
out[i] = np.nan | ||
continue | ||
|
||
dt64_to_dtstruct(dtindex[i], &dts) | ||
out[i] = names[dts.month].capitalize() | ||
return out | ||
|
||
raise ValueError("Field %s not supported" % field) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,7 +24,7 @@ cimport ccalendar | |
from conversion import tz_localize_to_utc, date_normalize | ||
from conversion cimport (tz_convert_single, _TSObject, | ||
convert_to_tsobject, convert_datetime_to_tsobject) | ||
from fields import get_date_field, get_start_end_field | ||
from fields import get_start_end_field, get_date_name_field | ||
from nattype import NaT | ||
from nattype cimport NPY_NAT | ||
from np_datetime import OutOfBoundsDatetime | ||
|
@@ -352,6 +352,16 @@ cdef class _Timestamp(datetime): | |
field, freqstr, month_kw) | ||
return out[0] | ||
|
||
cpdef _get_date_name_field(self, object field, object locale): | ||
cdef: | ||
int64_t val | ||
ndarray out | ||
|
||
val = self._maybe_convert_value_to_local() | ||
out = get_date_name_field(np.array([val], dtype=np.int64), | ||
field, locale=locale) | ||
return out[0] | ||
|
||
@property | ||
def _repr_base(self): | ||
return '{date} {time}'.format(date=self._date_repr, | ||
|
@@ -714,12 +724,50 @@ class Timestamp(_Timestamp): | |
def dayofweek(self): | ||
return self.weekday() | ||
|
||
def day_name(self, locale=None): | ||
""" | ||
Return the day name of the Timestamp with specified locale. | ||
|
||
Parameters | ||
---------- | ||
locale : string, default None (English locale) | ||
locale determining the language in which to return the day name | ||
|
||
Returns | ||
------- | ||
day_name : string | ||
|
||
.. versionadded:: 0.23.0 | ||
""" | ||
return self._get_date_name_field('day_name', locale) | ||
|
||
def month_name(self, locale=None): | ||
""" | ||
Return the month name of the Timestamp with specified locale. | ||
|
||
Parameters | ||
---------- | ||
locale : string, default None (English locale) | ||
locale determining the language in which to return the month name | ||
|
||
Returns | ||
------- | ||
month_name : string | ||
|
||
.. versionadded:: 0.23.0 | ||
""" | ||
return self._get_date_name_field('month_name', locale) | ||
|
||
@property | ||
def weekday_name(self): | ||
cdef dict wdays = {0: 'Monday', 1: 'Tuesday', 2: 'Wednesday', | ||
3: 'Thursday', 4: 'Friday', 5: 'Saturday', | ||
6: 'Sunday'} | ||
return wdays[self.weekday()] | ||
""" | ||
.. deprecated:: 0.23.0 | ||
Use ``Timestamp.day_name()`` instead | ||
""" | ||
warnings.warn("`weekday_name` is deprecated and will be removed in a " | ||
"future version. Use `day_name` instead", | ||
DeprecationWarning) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can u have this call day_name |
||
return self.day_name() | ||
|
||
@property | ||
def dayofyear(self): | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if weekday_name is anywhere here can you remove