Skip to content

Commit 607910b

Browse files
mroeschkejreback
authored andcommitted
Add month names (#18164)
1 parent 2fad756 commit 607910b

File tree

10 files changed

+330
-61
lines changed

10 files changed

+330
-61
lines changed

doc/source/api.rst

+6-3
Original file line numberDiff line numberDiff line change
@@ -551,7 +551,6 @@ These can be accessed like ``Series.dt.<property>``.
551551
Series.dt.weekofyear
552552
Series.dt.dayofweek
553553
Series.dt.weekday
554-
Series.dt.weekday_name
555554
Series.dt.dayofyear
556555
Series.dt.quarter
557556
Series.dt.is_month_start
@@ -581,6 +580,8 @@ These can be accessed like ``Series.dt.<property>``.
581580
Series.dt.round
582581
Series.dt.floor
583582
Series.dt.ceil
583+
Series.dt.month_name
584+
Series.dt.day_name
584585

585586
**Timedelta Properties**
586587

@@ -1723,7 +1724,6 @@ Time/Date Components
17231724
DatetimeIndex.week
17241725
DatetimeIndex.dayofweek
17251726
DatetimeIndex.weekday
1726-
DatetimeIndex.weekday_name
17271727
DatetimeIndex.quarter
17281728
DatetimeIndex.tz
17291729
DatetimeIndex.freq
@@ -1759,6 +1759,8 @@ Time-specific operations
17591759
DatetimeIndex.round
17601760
DatetimeIndex.floor
17611761
DatetimeIndex.ceil
1762+
DatetimeIndex.month_name
1763+
DatetimeIndex.day_name
17621764

17631765
Conversion
17641766
~~~~~~~~~~
@@ -1940,7 +1942,6 @@ Properties
19401942
Timestamp.tzinfo
19411943
Timestamp.value
19421944
Timestamp.week
1943-
Timestamp.weekday_name
19441945
Timestamp.weekofyear
19451946
Timestamp.year
19461947

@@ -1954,6 +1955,7 @@ Methods
19541955
Timestamp.combine
19551956
Timestamp.ctime
19561957
Timestamp.date
1958+
Timestamp.day_name
19571959
Timestamp.dst
19581960
Timestamp.floor
19591961
Timestamp.freq
@@ -1963,6 +1965,7 @@ Methods
19631965
Timestamp.isocalendar
19641966
Timestamp.isoformat
19651967
Timestamp.isoweekday
1968+
Timestamp.month_name
19661969
Timestamp.normalize
19671970
Timestamp.now
19681971
Timestamp.replace

doc/source/whatsnew/v0.23.0.txt

+3-1
Original file line numberDiff line numberDiff line change
@@ -338,7 +338,8 @@ Other Enhancements
338338
- For subclassed ``DataFrames``, :func:`DataFrame.apply` will now preserve the ``Series`` subclass (if defined) when passing the data to the applied function (:issue:`19822`)
339339
- :func:`DataFrame.from_dict` now accepts a ``columns`` argument that can be used to specify the column names when ``orient='index'`` is used (:issue:`18529`)
340340
- Added option ``display.html.use_mathjax`` so `MathJax <https://www.mathjax.org/>`_ can be disabled when rendering tables in ``Jupyter`` notebooks (:issue:`19856`, :issue:`19824`)
341-
341+
- :meth:`Timestamp.month_name`, :meth:`DatetimeIndex.month_name`, and :meth:`Series.dt.month_name` are now available (:issue:`12805`)
342+
- :meth:`Timestamp.day_name` and :meth:`DatetimeIndex.day_name` are now available to return day names with a specified locale (:issue:`12806`)
342343

343344
.. _whatsnew_0230.api_breaking:
344345

@@ -728,6 +729,7 @@ Deprecations
728729
- The ``broadcast`` parameter of ``.apply()`` is deprecated in favor of ``result_type='broadcast'`` (:issue:`18577`)
729730
- The ``reduce`` parameter of ``.apply()`` is deprecated in favor of ``result_type='reduce'`` (:issue:`18577`)
730731
- The ``order`` parameter of :func:`factorize` is deprecated and will be removed in a future release (:issue:`19727`)
732+
- :attr:`Timestamp.weekday_name`, :attr:`DatetimeIndex.weekday_name`, and :attr:`Series.dt.weekday_name` are deprecated in favor of :meth:`Timestamp.day_name`, :meth:`DatetimeIndex.day_name`, and :meth:`Series.dt.day_name` (:issue:`12806`)
731733

732734
.. _whatsnew_0230.prior_deprecations:
733735

pandas/_libs/tslibs/ccalendar.pyx

+29
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ cimport numpy as cnp
1212
from numpy cimport int64_t, int32_t
1313
cnp.import_array()
1414

15+
from locale import LC_TIME
16+
from strptime import LocaleTime
1517

1618
# ----------------------------------------------------------------------
1719
# Constants
@@ -35,11 +37,18 @@ cdef int32_t* _month_offset = [
3537
# Canonical location for other modules to find name constants
3638
MONTHS = ['JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL',
3739
'AUG', 'SEP', 'OCT', 'NOV', 'DEC']
40+
# The first blank line is consistent with calendar.month_name in the calendar
41+
# standard library
42+
MONTHS_FULL = ['', 'January', 'February', 'March', 'April', 'May', 'June',
43+
'July', 'August', 'September', 'October', 'November',
44+
'December']
3845
MONTH_NUMBERS = {name: num for num, name in enumerate(MONTHS)}
3946
MONTH_ALIASES = {(num + 1): name for num, name in enumerate(MONTHS)}
4047
MONTH_TO_CAL_NUM = {name: num + 1 for num, name in enumerate(MONTHS)}
4148

4249
DAYS = ['MON', 'TUE', 'WED', 'THU', 'FRI', 'SAT', 'SUN']
50+
DAYS_FULL = ['Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday',
51+
'Saturday', 'Sunday']
4352
int_to_weekday = {num: name for num, name in enumerate(DAYS)}
4453
weekday_to_int = {int_to_weekday[key]: key for key in int_to_weekday}
4554

@@ -199,3 +208,23 @@ cpdef int32_t get_day_of_year(int year, int month, int day) nogil:
199208

200209
day_of_year = mo_off + day
201210
return day_of_year
211+
212+
213+
cpdef get_locale_names(object name_type, object locale=None):
214+
"""Returns an array of localized day or month names
215+
216+
Parameters
217+
----------
218+
name_type : string, attribute of LocaleTime() in which to return localized
219+
names
220+
locale : string
221+
222+
Returns
223+
-------
224+
list of locale names
225+
226+
"""
227+
from pandas.util.testing import set_locale
228+
229+
with set_locale(locale, LC_TIME):
230+
return getattr(LocaleTime(), name_type)

pandas/_libs/tslibs/fields.pyx

+25-10
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ cimport numpy as cnp
1313
from numpy cimport ndarray, int64_t, int32_t, int8_t
1414
cnp.import_array()
1515

16-
16+
from ccalendar import get_locale_names, MONTHS_FULL, DAYS_FULL
1717
from ccalendar cimport (get_days_in_month, is_leapyear, dayofweek,
1818
get_week_of_year, get_day_of_year)
1919
from np_datetime cimport (pandas_datetimestruct, pandas_timedeltastruct,
@@ -85,34 +85,49 @@ def build_field_sarray(ndarray[int64_t] dtindex):
8585

8686
@cython.wraparound(False)
8787
@cython.boundscheck(False)
88-
def get_date_name_field(ndarray[int64_t] dtindex, object field):
88+
def get_date_name_field(ndarray[int64_t] dtindex, object field,
89+
object locale=None):
8990
"""
9091
Given a int64-based datetime index, return array of strings of date
9192
name based on requested field (e.g. weekday_name)
9293
"""
9394
cdef:
9495
Py_ssize_t i, count = 0
95-
ndarray[object] out
96+
ndarray[object] out, names
9697
pandas_datetimestruct dts
9798
int dow
9899

99-
_dayname = np.array(
100-
['Monday', 'Tuesday', 'Wednesday', 'Thursday',
101-
'Friday', 'Saturday', 'Sunday'],
102-
dtype=np.object_)
103-
104100
count = len(dtindex)
105101
out = np.empty(count, dtype=object)
106102

107-
if field == 'weekday_name':
103+
if field == 'day_name' or field == 'weekday_name':
104+
if locale is None:
105+
names = np.array(DAYS_FULL, dtype=np.object_)
106+
else:
107+
names = np.array(get_locale_names('f_weekday', locale),
108+
dtype=np.object_)
108109
for i in range(count):
109110
if dtindex[i] == NPY_NAT:
110111
out[i] = np.nan
111112
continue
112113

113114
dt64_to_dtstruct(dtindex[i], &dts)
114115
dow = dayofweek(dts.year, dts.month, dts.day)
115-
out[i] = _dayname[dow]
116+
out[i] = names[dow].capitalize()
117+
return out
118+
elif field == 'month_name':
119+
if locale is None:
120+
names = np.array(MONTHS_FULL, dtype=np.object_)
121+
else:
122+
names = np.array(get_locale_names('f_month', locale),
123+
dtype=np.object_)
124+
for i in range(count):
125+
if dtindex[i] == NPY_NAT:
126+
out[i] = np.nan
127+
continue
128+
129+
dt64_to_dtstruct(dtindex[i], &dts)
130+
out[i] = names[dts.month].capitalize()
116131
return out
117132

118133
raise ValueError("Field %s not supported" % field)

pandas/_libs/tslibs/nattype.pyx

+36-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
# -*- coding: utf-8 -*-
22
# cython: profile=False
3-
import warnings
43

54
from cpython cimport (
65
PyFloat_Check, PyComplex_Check,
@@ -39,24 +38,19 @@ _nat_scalar_rules[Py_GE] = False
3938
# ----------------------------------------------------------------------
4039

4140

42-
def _make_nan_func(func_name, cls):
41+
def _make_nan_func(func_name, doc):
4342
def f(*args, **kwargs):
4443
return np.nan
4544
f.__name__ = func_name
46-
f.__doc__ = getattr(cls, func_name).__doc__
45+
f.__doc__ = doc
4746
return f
4847

4948

50-
def _make_nat_func(func_name, cls):
49+
def _make_nat_func(func_name, doc):
5150
def f(*args, **kwargs):
5251
return NaT
53-
5452
f.__name__ = func_name
55-
if isinstance(cls, str):
56-
# passed the literal docstring directly
57-
f.__doc__ = cls
58-
else:
59-
f.__doc__ = getattr(cls, func_name).__doc__
53+
f.__doc__ = doc
6054
return f
6155

6256

@@ -318,11 +312,40 @@ class NaTType(_NaT):
318312
# These are the ones that can get their docstrings from datetime.
319313

320314
# nan methods
321-
weekday = _make_nan_func('weekday', datetime)
322-
isoweekday = _make_nan_func('isoweekday', datetime)
315+
weekday = _make_nan_func('weekday', datetime.weekday.__doc__)
316+
isoweekday = _make_nan_func('isoweekday', datetime.isoweekday.__doc__)
317+
month_name = _make_nan_func('month_name', # noqa:E128
318+
"""
319+
Return the month name of the Timestamp with specified locale.
320+
321+
Parameters
322+
----------
323+
locale : string, default None (English locale)
324+
locale determining the language in which to return the month name
325+
326+
Returns
327+
-------
328+
month_name : string
329+
330+
.. versionadded:: 0.23.0
331+
""")
332+
day_name = _make_nan_func('day_name', # noqa:E128
333+
"""
334+
Return the day name of the Timestamp with specified locale.
323335
336+
Parameters
337+
----------
338+
locale : string, default None (English locale)
339+
locale determining the language in which to return the day name
340+
341+
Returns
342+
-------
343+
day_name : string
344+
345+
.. versionadded:: 0.23.0
346+
""")
324347
# _nat_methods
325-
date = _make_nat_func('date', datetime)
348+
date = _make_nat_func('date', datetime.date.__doc__)
326349

327350
utctimetuple = _make_error_func('utctimetuple', datetime)
328351
timetz = _make_error_func('timetz', datetime)

pandas/_libs/tslibs/timestamps.pyx

+53-5
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ cimport ccalendar
2424
from conversion import tz_localize_to_utc, date_normalize
2525
from conversion cimport (tz_convert_single, _TSObject,
2626
convert_to_tsobject, convert_datetime_to_tsobject)
27-
from fields import get_date_field, get_start_end_field
27+
from fields import get_start_end_field, get_date_name_field
2828
from nattype import NaT
2929
from nattype cimport NPY_NAT
3030
from np_datetime import OutOfBoundsDatetime
@@ -352,6 +352,16 @@ cdef class _Timestamp(datetime):
352352
field, freqstr, month_kw)
353353
return out[0]
354354

355+
cpdef _get_date_name_field(self, object field, object locale):
356+
cdef:
357+
int64_t val
358+
ndarray out
359+
360+
val = self._maybe_convert_value_to_local()
361+
out = get_date_name_field(np.array([val], dtype=np.int64),
362+
field, locale=locale)
363+
return out[0]
364+
355365
@property
356366
def _repr_base(self):
357367
return '{date} {time}'.format(date=self._date_repr,
@@ -714,12 +724,50 @@ class Timestamp(_Timestamp):
714724
def dayofweek(self):
715725
return self.weekday()
716726

727+
def day_name(self, locale=None):
728+
"""
729+
Return the day name of the Timestamp with specified locale.
730+
731+
Parameters
732+
----------
733+
locale : string, default None (English locale)
734+
locale determining the language in which to return the day name
735+
736+
Returns
737+
-------
738+
day_name : string
739+
740+
.. versionadded:: 0.23.0
741+
"""
742+
return self._get_date_name_field('day_name', locale)
743+
744+
def month_name(self, locale=None):
745+
"""
746+
Return the month name of the Timestamp with specified locale.
747+
748+
Parameters
749+
----------
750+
locale : string, default None (English locale)
751+
locale determining the language in which to return the month name
752+
753+
Returns
754+
-------
755+
month_name : string
756+
757+
.. versionadded:: 0.23.0
758+
"""
759+
return self._get_date_name_field('month_name', locale)
760+
717761
@property
718762
def weekday_name(self):
719-
cdef dict wdays = {0: 'Monday', 1: 'Tuesday', 2: 'Wednesday',
720-
3: 'Thursday', 4: 'Friday', 5: 'Saturday',
721-
6: 'Sunday'}
722-
return wdays[self.weekday()]
763+
"""
764+
.. deprecated:: 0.23.0
765+
Use ``Timestamp.day_name()`` instead
766+
"""
767+
warnings.warn("`weekday_name` is deprecated and will be removed in a "
768+
"future version. Use `day_name` instead",
769+
DeprecationWarning)
770+
return self.day_name()
723771

724772
@property
725773
def dayofyear(self):

0 commit comments

Comments
 (0)