From c095833b6bfc66add8aab5233761e756393198ce Mon Sep 17 00:00:00 2001 From: Jeff Reback Date: Mon, 12 Oct 2015 11:43:53 -0400 Subject: [PATCH] BUG: Bug in tz-conversions with an ambiguous time and .dt accessors, #11295 --- doc/source/whatsnew/v0.17.1.txt | 4 ++++ pandas/tests/test_index.py | 9 +++++++++ pandas/tests/test_series.py | 12 ++++++++++++ pandas/tseries/common.py | 4 +++- pandas/tseries/frequencies.py | 9 +++++---- pandas/tseries/index.py | 12 +++--------- 6 files changed, 36 insertions(+), 14 deletions(-) diff --git a/doc/source/whatsnew/v0.17.1.txt b/doc/source/whatsnew/v0.17.1.txt index e4372ad1d23b8..79eef77b74ff7 100755 --- a/doc/source/whatsnew/v0.17.1.txt +++ b/doc/source/whatsnew/v0.17.1.txt @@ -55,8 +55,12 @@ Bug Fixes - Bug in ``.to_latex()`` output broken when the index has a name (:issue: `10660`) - Bug in ``HDFStore.append`` with strings whose encoded length exceded the max unencoded length (:issue:`11234`) + - Bug in ``HDFStore.select`` when comparing with a numpy scalar in a where clause (:issue:`11283`) +- Bug in tz-conversions with an ambiguous time and ``.dt`` accessors (:issues:`11295`) + + diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py index 81ebc7efdbdd9..f7d93a978a46a 100644 --- a/pandas/tests/test_index.py +++ b/pandas/tests/test_index.py @@ -3348,6 +3348,15 @@ def test_construction_with_alt(self): i2 = DatetimeIndex(i.tz_localize(None).asi8, dtype=i.dtype, tz=i.dtype.tz) self.assert_index_equal(i, i2) + # localize into the provided tz + i2 = DatetimeIndex(i.tz_localize(None).asi8, tz='UTC') + expected = i.tz_localize(None).tz_localize('UTC') + self.assert_index_equal(i2, expected) + + i2 = DatetimeIndex(i, tz='UTC') + expected = i.tz_convert('UTC') + self.assert_index_equal(i2, expected) + # incompat tz/dtype self.assertRaises(ValueError, lambda : DatetimeIndex(i.tz_localize(None).asi8, dtype=i.dtype, tz='US/Pacific')) diff --git a/pandas/tests/test_series.py b/pandas/tests/test_series.py index 3a13af60ae86f..9c86c3f894c67 100644 --- a/pandas/tests/test_series.py +++ b/pandas/tests/test_series.py @@ -224,6 +224,18 @@ def get_dir(s): results = get_dir(s) tm.assert_almost_equal(results, list(sorted(set(ok_for_period + ok_for_period_methods)))) + # 11295 + # ambiguous time error on the conversions + s = Series(pd.date_range('2015-01-01', '2016-01-01', freq='T')) + s = s.dt.tz_localize('UTC').dt.tz_convert('America/Chicago') + results = get_dir(s) + tm.assert_almost_equal(results, list(sorted(set(ok_for_dt + ok_for_dt_methods)))) + expected = Series(pd.date_range('2015-01-01', + '2016-01-01', + freq='T', + tz='UTC').tz_convert('America/Chicago')) + tm.assert_series_equal(s, expected) + # no setting allowed s = Series(date_range('20130101',periods=5,freq='D')) with tm.assertRaisesRegexp(ValueError, "modifications"): diff --git a/pandas/tseries/common.py b/pandas/tseries/common.py index ba9f2b8343a3d..dcfe809074a0b 100644 --- a/pandas/tseries/common.py +++ b/pandas/tseries/common.py @@ -45,8 +45,10 @@ def maybe_to_datetimelike(data, copy=False): raise TypeError("cannot convert an object of type {0} to a datetimelike index".format(type(data))) index = data.index - if is_datetime64_dtype(data.dtype) or is_datetime64tz_dtype(data.dtype): + if is_datetime64_dtype(data.dtype): return DatetimeProperties(DatetimeIndex(data, copy=copy, freq='infer'), index, name=data.name) + elif is_datetime64tz_dtype(data.dtype): + return DatetimeProperties(DatetimeIndex(data, copy=copy, freq='infer', ambiguous='infer'), index, name=data.name) elif is_timedelta64_dtype(data.dtype): return TimedeltaProperties(TimedeltaIndex(data, copy=copy, freq='infer'), index, name=data.name) else: diff --git a/pandas/tseries/frequencies.py b/pandas/tseries/frequencies.py index 6a4257d101473..07546a76be431 100644 --- a/pandas/tseries/frequencies.py +++ b/pandas/tseries/frequencies.py @@ -851,10 +851,11 @@ def infer_freq(index, warn=True): raise TypeError("cannot infer freq from a non-convertible index type {0}".format(type(index))) index = index.values - try: - index = pd.DatetimeIndex(index) - except AmbiguousTimeError: - index = pd.DatetimeIndex(index.asi8) + if not isinstance(index, pd.DatetimeIndex): + try: + index = pd.DatetimeIndex(index) + except AmbiguousTimeError: + index = pd.DatetimeIndex(index.asi8) inferer = _FrequencyInferer(index, warn=warn) return inferer.get_freq() diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index 8f6b924ebd850..814a9ccc45582 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -194,7 +194,8 @@ def _join_i8_wrapper(joinf, **kwargs): _datetimelike_ops = ['year','month','day','hour','minute','second', 'weekofyear','week','dayofweek','weekday','dayofyear','quarter', 'days_in_month', 'daysinmonth', 'date','time','microsecond','nanosecond','is_month_start','is_month_end', - 'is_quarter_start','is_quarter_end','is_year_start','is_year_end','tz','freq'] + 'is_quarter_start','is_quarter_end','is_year_start','is_year_end', + 'tz','freq'] _is_numeric_dtype = False @@ -269,14 +270,7 @@ def __new__(cls, data=None, dayfirst=dayfirst, yearfirst=yearfirst) - if is_datetimetz(data): - # extract the data whether a Series or Index - if isinstance(data, ABCSeries): - data = data._values - tz = data.tz - data = data.tz_localize(None, ambiguous='infer').values - - if issubclass(data.dtype.type, np.datetime64): + if issubclass(data.dtype.type, np.datetime64) or is_datetimetz(data): if isinstance(data, ABCSeries): data = data._values if isinstance(data, DatetimeIndex):