From 4c67a9c730bc5e6771f87f25c64fb7afd77858ab Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sun, 30 Sep 2018 18:30:20 -0700 Subject: [PATCH 1/2] BUG: to_datetime preserves name of Index argument in the result --- doc/source/whatsnew/v0.24.0.txt | 1 + pandas/core/tools/datetimes.py | 13 ++++++++----- pandas/tests/indexes/datetimes/test_tools.py | 10 ++++++++++ 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 3e1711edb0f27..d9b898ceaf807 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -652,6 +652,7 @@ Datetimelike - Bug in :class:`DatetimeIndex` subtraction that incorrectly failed to raise ``OverflowError`` (:issue:`22492`, :issue:`22508`) - Bug in :class:`DatetimeIndex` incorrectly allowing indexing with ``Timedelta`` object (:issue:`20464`) - Bug in :class:`DatetimeIndex` where frequency was being set if original frequency was ``None`` (:issue:`22150`) +- Bug in :func:`to_datetime` with an :class:`Index` argument that would drop the ``name`` from the result (:issue:`21697`) Timedelta ^^^^^^^^^ diff --git a/pandas/core/tools/datetimes.py b/pandas/core/tools/datetimes.py index 57387b9ea870a..4a5290a90313d 100644 --- a/pandas/core/tools/datetimes.py +++ b/pandas/core/tools/datetimes.py @@ -99,13 +99,13 @@ def _convert_and_box_cache(arg, cache_array, box, errors, name=None): result = Series(arg).map(cache_array) if box: if errors == 'ignore': - return Index(result) + return Index(result, name=name) else: return DatetimeIndex(result, name=name) return result.values -def _return_parsed_timezone_results(result, timezones, box, tz): +def _return_parsed_timezone_results(result, timezones, box, tz, name): """ Return results from array_strptime if a %z or %Z directive was passed. @@ -119,6 +119,9 @@ def _return_parsed_timezone_results(result, timezones, box, tz): True boxes result as an Index-like, False returns an ndarray tz : object None or pytz timezone object + name : string, default None + Name for a DatetimeIndex + Returns ------- tz_result : ndarray of parsed dates with timezone @@ -136,7 +139,7 @@ def _return_parsed_timezone_results(result, timezones, box, tz): in zip(result, timezones)]) if box: from pandas import Index - return Index(tz_results) + return Index(tz_results, name=name) return tz_results @@ -209,7 +212,7 @@ def _convert_listlike_datetimes(arg, box, format, name=None, tz=None, if box: if errors == 'ignore': from pandas import Index - return Index(result) + return Index(result, name=name) return DatetimeIndex(result, tz=tz, name=name) return result @@ -252,7 +255,7 @@ def _convert_listlike_datetimes(arg, box, format, name=None, tz=None, arg, format, exact=exact, errors=errors) if '%Z' in format or '%z' in format: return _return_parsed_timezone_results( - result, timezones, box, tz) + result, timezones, box, tz, name) except tslibs.OutOfBoundsDatetime: if errors == 'raise': raise diff --git a/pandas/tests/indexes/datetimes/test_tools.py b/pandas/tests/indexes/datetimes/test_tools.py index cc6db8f5854c8..e7f1267d07783 100644 --- a/pandas/tests/indexes/datetimes/test_tools.py +++ b/pandas/tests/indexes/datetimes/test_tools.py @@ -6,6 +6,7 @@ import calendar import dateutil import numpy as np +from functools import partial from dateutil.parser import parse from dateutil.tz.tz import tzoffset from datetime import datetime, time @@ -182,6 +183,7 @@ def test_to_datetime_format_weeks(self, cache): @pytest.mark.parametrize("box,const,assert_equal", [ [True, pd.Index, 'assert_index_equal'], + [True, partial(pd.Index, name='foo'), 'assert_index_equal'], [False, np.array, 'assert_numpy_array_equal']]) @pytest.mark.parametrize("fmt,dates,expected_dates", [ ['%Y-%m-%d %H:%M:%S %Z', @@ -765,6 +767,14 @@ def test_unit_rounding(self, cache): expected = pd.Timestamp('2015-06-19 19:55:31.877000093') assert result == expected + @pytest.mark.parametrize('cache', [True, False]) + def test_unit_ignore_keeps_name(self, cache): + # GH 21697 + expected = pd.Index([15e9] * 2, name='name') + result = pd.to_datetime(expected, errors='ignore', box=True, unit='s', + cache=cache) + tm.assert_index_equal(result, expected) + @pytest.mark.parametrize('cache', [True, False]) def test_dataframe(self, cache): From a7e1410aad78f9373499fed155d16be55e5b5023 Mon Sep 17 00:00:00 2001 From: Matt Roeschke Date: Sun, 30 Sep 2018 18:45:27 -0700 Subject: [PATCH 2/2] correct test --- pandas/tests/indexes/datetimes/test_tools.py | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/pandas/tests/indexes/datetimes/test_tools.py b/pandas/tests/indexes/datetimes/test_tools.py index e7f1267d07783..3b7d6a709230b 100644 --- a/pandas/tests/indexes/datetimes/test_tools.py +++ b/pandas/tests/indexes/datetimes/test_tools.py @@ -6,7 +6,6 @@ import calendar import dateutil import numpy as np -from functools import partial from dateutil.parser import parse from dateutil.tz.tz import tzoffset from datetime import datetime, time @@ -183,7 +182,6 @@ def test_to_datetime_format_weeks(self, cache): @pytest.mark.parametrize("box,const,assert_equal", [ [True, pd.Index, 'assert_index_equal'], - [True, partial(pd.Index, name='foo'), 'assert_index_equal'], [False, np.array, 'assert_numpy_array_equal']]) @pytest.mark.parametrize("fmt,dates,expected_dates", [ ['%Y-%m-%d %H:%M:%S %Z', @@ -235,6 +233,15 @@ def test_to_datetime_parse_timezone_malformed(self, offset): with pytest.raises(ValueError): pd.to_datetime([date], format=fmt) + def test_to_datetime_parse_timezone_keeps_name(self): + # GH 21697 + fmt = '%Y-%m-%d %H:%M:%S %z' + arg = pd.Index(['2010-01-01 12:00:00 Z'], name='foo') + result = pd.to_datetime(arg, format=fmt) + expected = pd.DatetimeIndex(['2010-01-01 12:00:00'], tz='UTC', + name='foo') + tm.assert_index_equal(result, expected) + class TestToDatetime(object): def test_to_datetime_pydatetime(self):