diff --git a/doc/source/whatsnew/v0.17.1.txt b/doc/source/whatsnew/v0.17.1.txt index 25b22230e5f3d..64d04df06851f 100755 --- a/doc/source/whatsnew/v0.17.1.txt +++ b/doc/source/whatsnew/v0.17.1.txt @@ -17,6 +17,7 @@ Highlights include: Enhancements ~~~~~~~~~~~~ +- ``DatetimeIndex`` now supports conversion to strings with astype(str)(:issue:`10442`) - Support for ``compression`` (gzip/bz2) in :method:`DataFrame.to_csv` (:issue:`7615`) diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index 814a9ccc45582..868057c675594 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -756,6 +756,8 @@ def astype(self, dtype): return self.asi8.copy() elif dtype == _NS_DTYPE and self.tz is not None: return self.tz_convert('UTC').tz_localize(None) + elif dtype == str: + return self._shallow_copy(values=self.format(), infer=True) else: # pragma: no cover raise ValueError('Cannot cast DatetimeIndex to dtype %s' % dtype) diff --git a/pandas/tseries/tests/test_base.py b/pandas/tseries/tests/test_base.py index 24edc54582ec1..4d353eccba972 100644 --- a/pandas/tseries/tests/test_base.py +++ b/pandas/tseries/tests/test_base.py @@ -45,6 +45,32 @@ def test_ops_properties_basic(self): self.assertEqual(s.day,10) self.assertRaises(AttributeError, lambda : s.weekday) + def test_astype_str(self): + # test astype string - #10442 + result = date_range('2012-01-01', periods=4, name='test_name').astype(str) + expected = Index(['2012-01-01', '2012-01-02', '2012-01-03','2012-01-04'], + name='test_name', dtype=object) + tm.assert_index_equal(result, expected) + + # test astype string with tz and name + result = date_range('2012-01-01', periods=3, name='test_name', tz='US/Eastern').astype(str) + expected = Index(['2012-01-01 00:00:00-05:00', '2012-01-02 00:00:00-05:00', + '2012-01-03 00:00:00-05:00'], name='test_name', dtype=object) + tm.assert_index_equal(result, expected) + + # test astype string with freqH and name + result = date_range('1/1/2011', periods=3, freq='H', name='test_name').astype(str) + expected = Index(['2011-01-01 00:00:00', '2011-01-01 01:00:00', '2011-01-01 02:00:00'], + name='test_name', dtype=object) + tm.assert_index_equal(result, expected) + + # test astype string with freqH and timezone + result = date_range('3/6/2012 00:00', periods=2, freq='H', + tz='Europe/London', name='test_name').astype(str) + expected = Index(['2012-03-06 00:00:00+00:00', '2012-03-06 01:00:00+00:00'], + dtype=object, name='test_name') + tm.assert_index_equal(result, expected) + def test_asobject_tolist(self): idx = pd.date_range(start='2013-01-01', periods=4, freq='M', name='idx') expected_list = [pd.Timestamp('2013-01-31'), pd.Timestamp('2013-02-28'), @@ -503,7 +529,6 @@ def test_infer_freq(self): tm.assert_index_equal(idx, result) self.assertEqual(result.freq, freq) - class TestTimedeltaIndexOps(Ops): def setUp(self): diff --git a/pandas/tseries/tests/test_timeseries.py b/pandas/tseries/tests/test_timeseries.py index a80bdf970cccb..230016f00374f 100644 --- a/pandas/tseries/tests/test_timeseries.py +++ b/pandas/tseries/tests/test_timeseries.py @@ -2223,6 +2223,7 @@ def test_append_join_nondatetimeindex(self): # it works rng.join(idx, how='outer') + def test_astype(self): rng = date_range('1/1/2000', periods=10) @@ -2235,6 +2236,17 @@ def test_astype(self): expected = date_range('1/1/2000', periods=10, tz='US/Eastern').tz_convert('UTC').tz_localize(None) tm.assert_index_equal(result, expected) + # BUG#10442 : testing astype(str) is correct for Series/DatetimeIndex + result = pd.Series(pd.date_range('2012-01-01', periods=3)).astype(str) + expected = pd.Series(['2012-01-01', '2012-01-02', '2012-01-03'], dtype=object) + tm.assert_series_equal(result, expected) + + result = Series(pd.date_range('2012-01-01', periods=3, tz='US/Eastern')).astype(str) + expected = Series(['2012-01-01 00:00:00-05:00', '2012-01-02 00:00:00-05:00', '2012-01-03 00:00:00-05:00'], + dtype=object) + tm.assert_series_equal(result, expected) + + def test_to_period_nofreq(self): idx = DatetimeIndex(['2000-01-01', '2000-01-02', '2000-01-04']) self.assertRaises(ValueError, idx.to_period)