diff --git a/doc/source/whatsnew/v0.15.2.txt b/doc/source/whatsnew/v0.15.2.txt index 1e84762b60caa..b740ac948dc05 100644 --- a/doc/source/whatsnew/v0.15.2.txt +++ b/doc/source/whatsnew/v0.15.2.txt @@ -97,6 +97,7 @@ Bug Fixes - ``sql_schema`` now generates dialect appropriate ``CREATE TABLE`` statements (:issue:`8697`) - ``slice`` string method now takes step into account (:issue:`8754`) - Bug in ``BlockManager`` where setting values with different type would break block integrity (:issue:`8850`) +- Bug in ``DatetimeIndex`` when using ``time`` object as key (:issue:`8667`) - Fix negative step support for label-based slices (:issue:`8753`) Old behavior: diff --git a/pandas/index.pyx b/pandas/index.pyx index 73d886f10b241..9be7e7404f3fe 100644 --- a/pandas/index.pyx +++ b/pandas/index.pyx @@ -545,8 +545,14 @@ cdef class DatetimeEngine(Int64Engine): val = _to_i8(val) return self._get_loc_duplicates(val) values = self._get_index_values() - conv = _to_i8(val) - loc = values.searchsorted(conv, side='left') + + try: + conv = _to_i8(val) + loc = values.searchsorted(conv, side='left') + except TypeError: + self._date_check_type(val) + raise KeyError(val) + if loc == len(values) or util.get_value_at(values, loc) != conv: raise KeyError(val) return loc diff --git a/pandas/tests/test_index.py b/pandas/tests/test_index.py index b7a18da3924c8..5265318d2c831 100644 --- a/pandas/tests/test_index.py +++ b/pandas/tests/test_index.py @@ -1886,6 +1886,27 @@ def test_reindex_preserves_tz_if_target_is_empty_list_or_array(self): self.assertEqual(str(index.reindex([])[0].tz), 'US/Eastern') self.assertEqual(str(index.reindex(np.array([]))[0].tz), 'US/Eastern') + def test_time_loc(self): # GH8667 + from datetime import time + from pandas.index import _SIZE_CUTOFF + + ns = _SIZE_CUTOFF + np.array([-100, 100]) + key = time(15, 11, 30) + start = key.hour * 3600 + key.minute * 60 + key.second + step = 24 * 3600 + + for n in ns: + idx = pd.date_range('2014-11-26', periods=n, freq='S') + ts = pd.Series(np.random.randn(n), index=idx) + i = np.arange(start, n, step) + + tm.assert_array_equal(ts.index.get_loc(key), i) + tm.assert_series_equal(ts[key], ts.iloc[i]) + + left, right = ts.copy(), ts.copy() + left[key] *= -10 + right.iloc[i] *= -10 + tm.assert_series_equal(left, right) class TestPeriodIndex(Base, tm.TestCase): _holder = PeriodIndex diff --git a/pandas/tseries/index.py b/pandas/tseries/index.py index 202e30cc2eb5e..e7c001ac57c0a 100644 --- a/pandas/tseries/index.py +++ b/pandas/tseries/index.py @@ -1210,6 +1210,10 @@ def get_value(self, series, key): return self.get_value_maybe_box(series, key) + if isinstance(key, time): + locs = self.indexer_at_time(key) + return series.take(locs) + try: return _maybe_box(self, Index.get_value(self, series, key), series, key) except KeyError: @@ -1219,10 +1223,6 @@ def get_value(self, series, key): except (TypeError, ValueError, KeyError): pass - if isinstance(key, time): - locs = self.indexer_at_time(key) - return series.take(locs) - try: return self.get_value_maybe_box(series, key) except (TypeError, ValueError, KeyError): @@ -1250,6 +1250,9 @@ def get_loc(self, key): stamp = Timestamp(key, tz=self.tz) return self._engine.get_loc(stamp) + if isinstance(key, time): + return self.indexer_at_time(key) + try: return Index.get_loc(self, key) except (KeyError, ValueError): @@ -1258,9 +1261,6 @@ def get_loc(self, key): except (TypeError, KeyError, ValueError): pass - if isinstance(key, time): - return self.indexer_at_time(key) - try: stamp = Timestamp(key, tz=self.tz) return self._engine.get_loc(stamp)