Repository: pandas-dev/pandas

Issue:
ENH: Add timetz attribute to DatetimeIndex and Timestamp
Currently `DatetimeIndex.time` returns a numpy array of local `datetime.time`s. In #18461, the resulting `datetime.time`s gained timezone information (but was an undocumented changed) and was subsequently reverted in #21281. Having `.time` return timezone information would still be a nice enhancement.

If we allow `DatetimeIndex.time` to return timezone information, [`timeseries.rst`](http://pandas.pydata.org/pandas-docs/stable/timeseries.html?highlight=weekofmonth#time-date-components) will need to be changed since it currently indicates that `.time` does not return timezone information.



Discussion:
Can I work on this? I'm new to working on pandas, but this seems like a fairly simple issue to get started with.







































































































































































































































































































































































 
Go for it @jquinon! The main job would be to undo the revision in #21281 make sure this change is documented. 
So now `DatetimeIndex.time` matches `datetime.time()` (minus the property vs method difference) which is an ideal consistency.

However, there is a `datetime.timetz()` method that returns time with timezone information. We could match the api and have a `DatetimeIndex.timetz` method, but I am not the biggest fan of the name.

I would prefer instead having `DatetimeIndex.time(tz=False)` that would match the method-like `time` api of the standard library, but use a keyword arg to return tz information.

Thoughts?
yeah that would be ok except it’s current a property - not sure we can change this
It would be an API change; otherwise, I don't recall an internal reason why we can't break it.
I am not sure this (adding a tz keyword) is worth the API change. Changing from a attribute to method is a quite big change, as every use of the current attribute would be impacted.
Fair enough. Should we then mimic the standard library and add a `.timetz` property?
> Should we then mimic the standard library and add a .timetz property?

I personally don't really care about adding it, but also won't object if others want it.
@jquinon if you're interested to add a timetz property to `DatetimeIndex` and `Timestamp`
If everyone is cool with it then sure. @jreback 
yep this sounds ok 

Resolving patch:
diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py
--- a/pandas/core/arrays/datetimes.py
+++ b/pandas/core/arrays/datetimes.py
@@ -856,6 +856,14 @@ def time(self):
 
         return tslib.ints_to_pydatetime(timestamps, box="time")
 
+    @property
+    def timetz(self):
+        """
+        Returns numpy array of datetime.time also containing timezone
+        information. The time part of the Timestamps.
+        """
+        return tslib.ints_to_pydatetime(self.asi8, self.tz, box="time")
+
     @property
     def date(self):
         """
diff --git a/pandas/core/indexes/datetimes.py b/pandas/core/indexes/datetimes.py
--- a/pandas/core/indexes/datetimes.py
+++ b/pandas/core/indexes/datetimes.py
@@ -170,6 +170,7 @@ class DatetimeIndex(DatetimeArrayMixin, DatelikeOps, TimelikeOps,
     nanosecond
     date
     time
+    timetz
     dayofyear
     weekofyear
     week
@@ -260,7 +261,7 @@ def _add_comparison_methods(cls):
                   'dayofyear', 'quarter', 'days_in_month',
                   'daysinmonth', 'microsecond',
                   'nanosecond']
-    _other_ops = ['date', 'time']
+    _other_ops = ['date', 'time', 'timetz']
     _datetimelike_ops = _field_ops + _object_ops + _bool_ops + _other_ops
     _datetimelike_methods = ['to_period', 'tz_localize',
                              'tz_convert',


Test patch:
diff --git a/pandas/tests/indexes/datetimes/test_timezones.py b/pandas/tests/indexes/datetimes/test_timezones.py
--- a/pandas/tests/indexes/datetimes/test_timezones.py
+++ b/pandas/tests/indexes/datetimes/test_timezones.py
@@ -731,6 +731,20 @@ def test_time_accessor(self, dtype):
 
         tm.assert_numpy_array_equal(result, expected)
 
+    def test_timetz_accessor(self, tz_naive_fixture):
+        # GH21358
+        if tz_naive_fixture is not None:
+            tz = dateutil.tz.gettz(tz_naive_fixture)
+        else:
+            tz = None
+
+        expected = np.array([time(10, 20, 30, tzinfo=tz), pd.NaT])
+
+        index = DatetimeIndex(['2018-06-04 10:20:30', pd.NaT], tz=tz)
+        result = index.timetz
+
+        tm.assert_numpy_array_equal(result, expected)
+
     def test_dti_drop_dont_lose_tz(self):
         # GH#2621
         ind = date_range("2012-12-01", periods=10, tz="utc")
diff --git a/pandas/tests/scalar/timestamp/test_timezones.py b/pandas/tests/scalar/timestamp/test_timezones.py
--- a/pandas/tests/scalar/timestamp/test_timezones.py
+++ b/pandas/tests/scalar/timestamp/test_timezones.py
@@ -2,7 +2,7 @@
 """
 Tests for Timestamp timezone-related methods
 """
-from datetime import date, timedelta
+from datetime import datetime, date, timedelta
 
 from distutils.version import LooseVersion
 import pytest
@@ -290,3 +290,20 @@ def test_timestamp_add_timedelta_push_over_dst_boundary(self, tz):
         expected = Timestamp('3/11/2012 05:00', tz=tz)
 
         assert result == expected
+
+    def test_timestamp_timetz_equivalent_with_datetime_tz(self,
+                                                          tz_naive_fixture):
+        # GH21358
+        if tz_naive_fixture is not None:
+            tz = dateutil.tz.gettz(tz_naive_fixture)
+        else:
+            tz = None
+
+        stamp = Timestamp('2018-06-04 10:20:30', tz=tz)
+        _datetime = datetime(2018, 6, 4, hour=10,
+                             minute=20, second=30, tzinfo=tz)
+
+        result = stamp.timetz()
+        expected = _datetime.timetz()
+
+        assert result == expected
diff --git a/pandas/tests/series/test_datetime_values.py b/pandas/tests/series/test_datetime_values.py
--- a/pandas/tests/series/test_datetime_values.py
+++ b/pandas/tests/series/test_datetime_values.py
@@ -5,7 +5,7 @@
 import calendar
 import pytest
 
-from datetime import datetime, date
+from datetime import datetime, time, date
 
 import numpy as np
 import pandas as pd
@@ -16,6 +16,8 @@
                     PeriodIndex, DatetimeIndex, TimedeltaIndex)
 import pandas.core.common as com
 
+import dateutil
+
 from pandas.util.testing import assert_series_equal
 import pandas.util.testing as tm
 
@@ -459,3 +461,18 @@ def test_datetime_understood(self):
         expected = pd.Series(pd.to_datetime([
             '2011-12-26', '2011-12-27', '2011-12-28']))
         tm.assert_series_equal(result, expected)
+
+    def test_dt_timetz_accessor(self, tz_naive_fixture):
+        # GH21358
+        if tz_naive_fixture is not None:
+            tz = dateutil.tz.gettz(tz_naive_fixture)
+        else:
+            tz = None
+
+        dtindex = pd.DatetimeIndex(['2014-04-04 23:56', '2014-07-18 21:24',
+                                    '2015-11-22 22:14'], tz=tz)
+        s = Series(dtindex)
+        expected = Series([time(23, 56, tzinfo=tz), time(21, 24, tzinfo=tz),
+                           time(22, 14, tzinfo=tz)])
+        result = s.dt.timetz
+        tm.assert_series_equal(result, expected)