Skip to content

ENH: Support times with timezones in at_time #25280

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Feb 16, 2019
2 changes: 1 addition & 1 deletion doc/source/whatsnew/v0.25.0.rst
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ Other Enhancements
^^^^^^^^^^^^^^^^^^

- :meth:`Timestamp.replace` now supports the ``fold`` argument to disambiguate DST transition times (:issue:`25017`)
-
- :meth:`DataFrame.at_time` and :meth:`Series.at_time` now support :meth:`datetime.time` objects with timezones (:issue:`24043`)
-

.. _whatsnew_0250.api_breaking:
Expand Down
13 changes: 6 additions & 7 deletions pandas/core/indexes/datetimes.py
Original file line number Diff line number Diff line change
Expand Up @@ -1302,20 +1302,19 @@ def indexer_at_time(self, time, asof=False):
--------
indexer_between_time, DataFrame.at_time
"""
from dateutil.parser import parse

if asof:
raise NotImplementedError("'asof' argument is not supported")

if isinstance(time, compat.string_types):
from dateutil.parser import parse
time = parse(time).time()

if time.tzinfo:
# TODO
raise NotImplementedError("argument 'time' with timezone info is "
"not supported")

time_micros = self._get_time_micros()
if self.tz is None:
raise ValueError("Index must be timezone aware.")
time_micros = self.tz_convert(time.tzinfo)._get_time_micros()
else:
time_micros = self._get_time_micros()
micros = _time_to_micros(time)
return (micros == time_micros).nonzero()[0]

Expand Down
23 changes: 23 additions & 0 deletions pandas/tests/frame/test_timeseries.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import numpy as np
import pytest
import pytz

from pandas.compat import product

Expand Down Expand Up @@ -647,6 +648,28 @@ def test_at_time(self):
rs = ts.at_time('16:00')
assert len(rs) == 0

@pytest.mark.parametrize('hour', ['1:00', '1:00AM', time(1),
time(1, tzinfo=pytz.UTC)])
def test_at_time_errors(self, hour):
# GH 24043
dti = pd.date_range('2018', periods=3, freq='H')
df = pd.DataFrame(list(range(len(dti))), index=dti)
if getattr(hour, 'tzinfo', None) is None:
result = df.at_time(hour)
expected = df.iloc[1:2]
tm.assert_frame_equal(result, expected)
else:
with pytest.raises(ValueError, match="Index must be timezone"):
df.at_time(hour)

def test_at_time_tz(self):
# GH 24043
dti = pd.date_range('2018', periods=3, freq='H', tz='US/Pacific')
df = pd.DataFrame(list(range(len(dti))), index=dti)
result = df.at_time(time(4, tzinfo=pytz.timezone('US/Eastern')))
expected = df.iloc[1:2]
tm.assert_frame_equal(result, expected)

def test_at_time_raises(self):
# GH20725
df = pd.DataFrame([[1, 2, 3], [4, 5, 6]])
Expand Down