Skip to content

Commit e27b9cb

Browse files
committed
ENH: support .strftime for datetimelikes (closes pandas-dev#10086)
1 parent eafd22d commit e27b9cb

File tree

4 files changed

+63
-9
lines changed

4 files changed

+63
-9
lines changed

pandas/tests/test_series.py

+29-8
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,10 @@ def test_dt_namespace_accessor(self):
8181

8282
ok_for_base = ['year','month','day','hour','minute','second','weekofyear','week','dayofweek','weekday','dayofyear','quarter','freq','days_in_month','daysinmonth']
8383
ok_for_period = ok_for_base + ['qyear']
84+
ok_for_period_methods = ['strftime']
8485
ok_for_dt = ok_for_base + ['date','time','microsecond','nanosecond', 'is_month_start', 'is_month_end', 'is_quarter_start',
8586
'is_quarter_end', 'is_year_start', 'is_year_end', 'tz']
86-
ok_for_dt_methods = ['to_period','to_pydatetime','tz_localize','tz_convert', 'normalize']
87+
ok_for_dt_methods = ['to_period','to_pydatetime','tz_localize','tz_convert', 'normalize', 'strftime']
8788
ok_for_td = ['days','seconds','microseconds','nanoseconds']
8889
ok_for_td_methods = ['components','to_pytimedelta']
8990

@@ -109,13 +110,12 @@ def compare(s, name):
109110
Series(date_range('20130101',periods=5,freq='s')),
110111
Series(date_range('20130101 00:00:00',periods=5,freq='ms'))]:
111112
for prop in ok_for_dt:
112-
113113
# we test freq below
114114
if prop != 'freq':
115115
compare(s, prop)
116116

117117
for prop in ok_for_dt_methods:
118-
getattr(s.dt,prop)
118+
getattr(s.dt, prop)
119119

120120
result = s.dt.to_pydatetime()
121121
self.assertIsInstance(result,np.ndarray)
@@ -140,13 +140,12 @@ def compare(s, name):
140140
Series(timedelta_range('1 day 01:23:45',periods=5,freq='s')),
141141
Series(timedelta_range('2 days 01:23:45.012345',periods=5,freq='ms'))]:
142142
for prop in ok_for_td:
143-
144143
# we test freq below
145144
if prop != 'freq':
146145
compare(s, prop)
147146

148147
for prop in ok_for_td_methods:
149-
getattr(s.dt,prop)
148+
getattr(s.dt, prop)
150149

151150
result = s.dt.components
152151
self.assertIsInstance(result,DataFrame)
@@ -169,13 +168,14 @@ def compare(s, name):
169168

170169
# periodindex
171170
for s in [Series(period_range('20130101',periods=5,freq='D'))]:
172-
173171
for prop in ok_for_period:
174-
175172
# we test freq below
176173
if prop != 'freq':
177174
compare(s, prop)
178175

176+
for prop in ok_for_period_methods:
177+
getattr(s.dt, prop)
178+
179179
freq_result = s.dt.freq
180180
self.assertEqual(freq_result, PeriodIndex(s.values).freq)
181181

@@ -190,7 +190,7 @@ def get_dir(s):
190190

191191
s = Series(period_range('20130101',periods=5,freq='D').asobject)
192192
results = get_dir(s)
193-
tm.assert_almost_equal(results,list(sorted(set(ok_for_period))))
193+
tm.assert_almost_equal(results, list(sorted(set(ok_for_period + ok_for_period_methods))))
194194

195195
# no setting allowed
196196
s = Series(date_range('20130101',periods=5,freq='D'))
@@ -203,6 +203,27 @@ def f():
203203
s.dt.hour[0] = 5
204204
self.assertRaises(com.SettingWithCopyError, f)
205205

206+
def test_strftime(self):
207+
# GH 10086
208+
s = Series(date_range('20130101', periods=5))
209+
result = s.dt.strftime('%Y/%m/%d')
210+
expected = Series(['2013/01/01', '2013/01/02', '2013/01/03', '2013/01/04', '2013/01/05'])
211+
tm.assert_series_equal(result, expected)
212+
213+
s.iloc[0] = pd.NaT
214+
result = s.dt.strftime('%Y/%m/%d')
215+
expected = Series(['NaT', '2013/01/02', '2013/01/03', '2013/01/04', '2013/01/05'])
216+
tm.assert_series_equal(result, expected)
217+
218+
datetime_index = date_range('20150301', periods=5)
219+
result = datetime_index.strftime("%Y/%m/%d")
220+
expected = ['2015/03/01', '2015/03/02', '2015/03/03', '2015/03/04', '2015/03/05']
221+
self.assertEqual(result, expected)
222+
223+
period_index = period_range('20150301', periods=5)
224+
expected = ['2015/03/01', '2015/03/02', '2015/03/03', '2015/03/04', '2015/03/05']
225+
self.assertEqual(result, expected)
226+
206227
def test_valid_dt_with_missing_values(self):
207228

208229
from datetime import date, time

pandas/tseries/common.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,7 @@ def to_pydatetime(self):
125125
accessors=DatetimeIndex._datetimelike_ops,
126126
typ='property')
127127
DatetimeProperties._add_delegate_accessors(delegate=DatetimeIndex,
128-
accessors=["to_period","tz_localize","tz_convert","normalize"],
128+
accessors=["to_period","tz_localize","tz_convert","normalize","strftime"],
129129
typ='method')
130130

131131
class TimedeltaProperties(Properties):
@@ -181,6 +181,9 @@ class PeriodProperties(Properties):
181181
PeriodProperties._add_delegate_accessors(delegate=PeriodIndex,
182182
accessors=PeriodIndex._datetimelike_ops,
183183
typ='property')
184+
PeriodProperties._add_delegate_accessors(delegate=PeriodIndex,
185+
accessors=["strftime"],
186+
typ='method')
184187

185188

186189
class CombinedDatetimelikeProperties(DatetimeProperties, TimedeltaProperties):

pandas/tseries/index.py

+15
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,21 @@ def astype(self, dtype):
694694
else: # pragma: no cover
695695
raise ValueError('Cannot cast DatetimeIndex to dtype %s' % dtype)
696696

697+
def strftime(self, date_format):
698+
"""
699+
Return a list of formmatted strings specified by date_format
700+
701+
Parameters
702+
----------
703+
date_format : str
704+
date format string (e.g. "%Y-%m-%d")
705+
706+
Returns
707+
-------
708+
a list formatted strings
709+
"""
710+
return self.format(date_format=date_format)
711+
697712
def _get_time_micros(self):
698713
utc = _utc()
699714
values = self.asi8

pandas/tseries/period.py

+15
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,21 @@ def astype(self, dtype):
328328
return Index(self.values, dtype)
329329
raise ValueError('Cannot cast PeriodIndex to dtype %s' % dtype)
330330

331+
def strftime(self, date_format):
332+
"""
333+
Return a list of formmatted strings specified by date_format
334+
335+
Parameters
336+
----------
337+
date_format : str
338+
date format string (e.g. "%Y-%m-%d")
339+
340+
Returns
341+
-------
342+
a list formatted strings
343+
"""
344+
return self.format(date_format=date_format)
345+
331346
def searchsorted(self, key, side='left'):
332347
if isinstance(key, Period):
333348
if key.freq != self.freq:

0 commit comments

Comments
 (0)