Skip to content

Commit d97f43b

Browse files
committed
Add month names
Fix localiztion of months Add series test and whatsnew notes Modify test and lint Add Timestamp rst Address comments Lint, move whatsnew, remove hardcoded Monday, check that get_locale is None create functions instead of attributes Fix white space Modify tests Lint Rebase and add depreciation message Deprecate weekday_name, create localizing function in ccalendar.pyx clean up imports Address user comments Try to address ci issues Rebase and adjust tests Move some imports to top of file, remove dup implimention of day_name in fields Fix failing test allow path to accept weekday_name as well address review address review missed files fix typo and call internal method Fix lint modify pytest param for appvoyer fix more appvoyer tests Remove weekday_name availability
1 parent 5f271eb commit d97f43b

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

@@ -677,6 +678,7 @@ Deprecations
677678
- The ``broadcast`` parameter of ``.apply()`` is deprecated in favor of ``result_type='broadcast'`` (:issue:`18577`)
678679
- The ``reduce`` parameter of ``.apply()`` is deprecated in favor of ``result_type='reduce'`` (:issue:`18577`)
679680
- The ``order`` parameter of :func:`factorize` is deprecated and will be removed in a future release (:issue:`19727`)
681+
- :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`)
680682

681683
.. _whatsnew_0230.prior_deprecations:
682684

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)