Skip to content

Commit ca6eb78

Browse files
committed
Add month names
Fix localiztion of months Add series test and whatsnew notes Modify test and lint Add Timestamp rst
1 parent 93c755e commit ca6eb78

File tree

7 files changed

+58
-31
lines changed

7 files changed

+58
-31
lines changed

doc/source/api.rst

+3
Original file line numberDiff line numberDiff line change
@@ -497,6 +497,7 @@ These can be accessed like ``Series.dt.<property>``.
497497
Series.dt.time
498498
Series.dt.year
499499
Series.dt.month
500+
Series.dt.month_name
500501
Series.dt.day
501502
Series.dt.hour
502503
Series.dt.minute
@@ -1537,6 +1538,7 @@ Time/Date Components
15371538

15381539
DatetimeIndex.year
15391540
DatetimeIndex.month
1541+
DatetimeIndex.month_name
15401542
DatetimeIndex.day
15411543
DatetimeIndex.hour
15421544
DatetimeIndex.minute
@@ -1757,6 +1759,7 @@ Properties
17571759
Timestamp.microsecond
17581760
Timestamp.min
17591761
Timestamp.month
1762+
Timestamp.month_name
17601763
Timestamp.nanosecond
17611764
Timestamp.quarter
17621765
Timestamp.resolution

doc/source/whatsnew/v0.21.1.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -22,8 +22,8 @@ Other Enhancements
2222
^^^^^^^^^^^^^^^^^^
2323

2424
- :meth:`Timestamp.timestamp` is now available in Python 2.7. (:issue:`17329`)
25-
-
26-
-
25+
- :attr:`Timestamp.month_name`, :attr:`DatetimeIndex.month_name`, and :attr:`Series.dt.month_name` are now available (:issue:`12805`)
26+
- ``month_name` and ``weekday_name`` attributes will now return locale aware values (:issue:`12806`)
2727

2828
.. _whatsnew_0211.deprecations:
2929

pandas/_libs/tslib.pyx

+10-4
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ from khash cimport (
6868
kh_resize_int64, kh_get_int64)
6969

7070
from .tslibs.parsing import parse_datetime_string
71+
from .tslibs.strptime import LocaleTime
7172

7273
cimport cython
7374

@@ -526,10 +527,15 @@ class Timestamp(_Timestamp):
526527

527528
@property
528529
def weekday_name(self):
529-
cdef dict wdays = {0: 'Monday', 1: 'Tuesday', 2: 'Wednesday',
530-
3: 'Thursday', 4: 'Friday', 5: 'Saturday',
531-
6: 'Sunday'}
532-
return wdays[self.weekday()]
530+
cdef object locale_time = LocaleTime()
531+
cdef dict wdays = dict(enumerate(locale_time.f_weekday))
532+
return wdays[self.weekday()].capitalize()
533+
534+
@property
535+
def month_name(self):
536+
cdef object locale_time = LocaleTime()
537+
cdef dict months = dict(enumerate(locale_time.f_month))
538+
return months[self.month].capitalize()
533539

534540
@property
535541
def dayofyear(self):

pandas/_libs/tslibs/fields.pyx

+14-6
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@ cimport util
2828

2929
cdef int64_t NPY_NAT = util.get_nat()
3030

31+
from pandas._libs.tslibs.strptime import LocaleTime
3132

3233
def build_field_sarray(ndarray[int64_t] dtindex):
3334
"""
@@ -83,24 +84,31 @@ def get_date_name_field(ndarray[int64_t] dtindex, object field):
8384
ndarray[object] out
8485
pandas_datetimestruct dts
8586
int dow
86-
87-
_dayname = np.array(
88-
['Monday', 'Tuesday', 'Wednesday', 'Thursday',
89-
'Friday', 'Saturday', 'Sunday'],
90-
dtype=np.object_)
87+
object locale_time = LocaleTime()
9188

9289
count = len(dtindex)
9390
out = np.empty(count, dtype=object)
9491

9592
if field == 'weekday_name':
93+
_dayname = np.array(locale_time.f_weekday, dtype=np.object_)
9694
for i in range(count):
9795
if dtindex[i] == NPY_NAT:
9896
out[i] = np.nan
9997
continue
10098

10199
dt64_to_dtstruct(dtindex[i], &dts)
102100
dow = dayofweek(dts.year, dts.month, dts.day)
103-
out[i] = _dayname[dow]
101+
out[i] = _dayname[dow].capitalize()
102+
return out
103+
elif field == 'month_name':
104+
_monthname = np.array(locale_time.f_month, dtype=np.object_)
105+
for i in range(count):
106+
if dtindex[i] == NPY_NAT:
107+
out[i] = np.nan
108+
continue
109+
110+
dt64_to_dtstruct(dtindex[i], &dts)
111+
out[i] = _monthname[dts.month].capitalize()
104112
return out
105113

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

pandas/core/indexes/datetimes.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@ def _join_i8_wrapper(joinf, **kwargs):
251251
_bool_ops = ['is_month_start', 'is_month_end',
252252
'is_quarter_start', 'is_quarter_end', 'is_year_start',
253253
'is_year_end', 'is_leap_year']
254-
_object_ops = ['weekday_name', 'freq', 'tz']
254+
_object_ops = ['weekday_name', 'month_name', 'freq', 'tz']
255255
_field_ops = ['year', 'month', 'day', 'hour', 'minute', 'second',
256256
'weekofyear', 'week', 'weekday', 'dayofweek',
257257
'dayofyear', 'quarter', 'days_in_month',
@@ -1588,6 +1588,11 @@ def _set_freq(self, value):
15881588
'weekday_name',
15891589
"The name of day in a week (ex: Friday)\n\n.. versionadded:: 0.18.1")
15901590

1591+
month_name = _field_accessor(
1592+
'month_name',
1593+
'month_name',
1594+
"The name of month in a year (ex: May)\n\n.. versionadded:: 0.21.1")
1595+
15911596
dayofyear = _field_accessor('dayofyear', 'doy',
15921597
"The ordinal day of the year")
15931598
quarter = _field_accessor('quarter', 'q', "The quarter of the date")

pandas/tests/indexes/datetimes/test_misc.py

+22-17
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,6 @@
1+
import locale
2+
import calendar
3+
14
import pytest
25

36
import numpy as np
@@ -172,8 +175,9 @@ def test_normalize(self):
172175

173176
class TestDatetime64(object):
174177

175-
def test_datetimeindex_accessors(self):
176-
178+
# GH 12806
179+
@pytest.mark.parametrize('time_locale', tm.get_locales())
180+
def test_datetimeindex_accessors(self, time_locale):
177181
dti_naive = DatetimeIndex(freq='D', start=datetime(1998, 1, 1),
178182
periods=365)
179183
# GH 13303
@@ -221,21 +225,12 @@ def test_datetimeindex_accessors(self):
221225
assert dti.is_year_end[364]
222226

223227
# GH 11128
224-
assert dti.weekday_name[4] == u'Monday'
225-
assert dti.weekday_name[5] == u'Tuesday'
226-
assert dti.weekday_name[6] == u'Wednesday'
227-
assert dti.weekday_name[7] == u'Thursday'
228-
assert dti.weekday_name[8] == u'Friday'
229-
assert dti.weekday_name[9] == u'Saturday'
230-
assert dti.weekday_name[10] == u'Sunday'
231-
232-
assert Timestamp('2016-04-04').weekday_name == u'Monday'
233-
assert Timestamp('2016-04-05').weekday_name == u'Tuesday'
234-
assert Timestamp('2016-04-06').weekday_name == u'Wednesday'
235-
assert Timestamp('2016-04-07').weekday_name == u'Thursday'
236-
assert Timestamp('2016-04-08').weekday_name == u'Friday'
237-
assert Timestamp('2016-04-09').weekday_name == u'Saturday'
238-
assert Timestamp('2016-04-10').weekday_name == u'Sunday'
228+
with tm.set_locale(time_locale, locale.LC_TIME):
229+
for day, name in zip(range(4, 11), calendar.day_name):
230+
# Test Monday -> Sunday
231+
assert dti.weekday_name[day] == name.capitalize()
232+
date = datetime(2016, 4, day)
233+
assert Timestamp(date).weekday_name == name.capitalize()
239234

240235
assert len(dti.year) == 365
241236
assert len(dti.month) == 365
@@ -342,6 +337,16 @@ def test_datetimeindex_accessors(self):
342337
assert dates.weekofyear.tolist() == expected
343338
assert [d.weekofyear for d in dates] == expected
344339

340+
# GH 12805
341+
with tm.set_locale(time_locale, locale.LC_TIME):
342+
dti = DatetimeIndex(freq='M', start='2012', end='2013')
343+
result = dti.month_name
344+
expected = Index([month.capitalize()
345+
for month in calendar.month_name[1:]])
346+
tm.assert_index_equal(result, expected)
347+
for date, result in zip(dti, calendar.month_name[1:]):
348+
assert date.month_name == result.capitalize()
349+
345350
def test_nanosecond_field(self):
346351
dti = DatetimeIndex(np.arange(10))
347352

pandas/tests/series/test_datetime_values.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ def test_dt_namespace_accessor(self):
3232
ok_for_dt = DatetimeIndex._datetimelike_ops
3333
ok_for_dt_methods = ['to_period', 'to_pydatetime', 'tz_localize',
3434
'tz_convert', 'normalize', 'strftime', 'round',
35-
'floor', 'ceil', 'weekday_name']
35+
'floor', 'ceil', 'weekday_name', 'month_name']
3636
ok_for_td = TimedeltaIndex._datetimelike_ops
3737
ok_for_td_methods = ['components', 'to_pytimedelta', 'total_seconds',
3838
'round', 'floor', 'ceil']

0 commit comments

Comments
 (0)