From 4578ce4efcc80f27092d75a196ef1aa907931e03 Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 13:28:13 -0400 Subject: [PATCH 1/8] ENH: Changed DatetimeIndex.time to also return timezone information --- pandas/_libs/tslib.pyx | 2 +- pandas/core/arrays/datetimes.py | 10 +--------- pandas/tests/indexes/datetimes/test_timezones.py | 12 ++++++------ 3 files changed, 8 insertions(+), 16 deletions(-) diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx index 281e497945c5f..bdf7808d0bb5d 100644 --- a/pandas/_libs/tslib.pyx +++ b/pandas/_libs/tslib.pyx @@ -74,7 +74,7 @@ cdef inline object create_time_from_ts( int64_t value, pandas_datetimestruct dts, object tz, object freq): """ convenience routine to construct a datetime.time from its parts """ - return time(dts.hour, dts.min, dts.sec, dts.us) + return time(dts.hour, dts.min, dts.sec, dts.us, tz) def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None, diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index 0d1c5241c5a93..bf229bcc54159 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -577,15 +577,7 @@ def time(self): """ Returns numpy array of datetime.time. The time part of the Timestamps. """ - # If the Timestamps have a timezone that is not UTC, - # convert them into their i8 representation while - # keeping their timezone and not using UTC - if self.tz is not None and self.tz is not utc: - timestamps = self._local_timestamps() - else: - timestamps = self.asi8 - - return tslib.ints_to_pydatetime(timestamps, box="time") + return tslib.ints_to_pydatetime(self.asi8, self.tz, box="time") @property def date(self): diff --git a/pandas/tests/indexes/datetimes/test_timezones.py b/pandas/tests/indexes/datetimes/test_timezones.py index 3697d183d2fc6..07dc65f9cd82e 100644 --- a/pandas/tests/indexes/datetimes/test_timezones.py +++ b/pandas/tests/indexes/datetimes/test_timezones.py @@ -718,15 +718,15 @@ def test_date_accessor(self, dtype): tm.assert_numpy_array_equal(result, expected) - @pytest.mark.parametrize("dtype", [ - None, 'datetime64[ns, CET]', - 'datetime64[ns, EST]', 'datetime64[ns, UTC]' + @pytest.mark.parametrize("tz", [ + None, pytz.timezone('CET'), pytz.timezone('EST'), + pytz.timezone('UTC') ]) - def test_time_accessor(self, dtype): + def test_time_accessor(self, tz): # Regression test for GH#21267 - expected = np.array([time(10, 20, 30), pd.NaT]) + expected = np.array([time(10, 20, 30, tzinfo=tz), pd.NaT]) - index = DatetimeIndex(['2018-06-04 10:20:30', pd.NaT], dtype=dtype) + index = DatetimeIndex(['2018-06-04 10:20:30', pd.NaT], tz=tz) result = index.time tm.assert_numpy_array_equal(result, expected) From 91db23d977e8d7c27d24fa8e8836e41613e41e26 Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 13:49:34 -0400 Subject: [PATCH 2/8] Added changes to the whatsnew doc --- doc/source/whatsnew/v0.24.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 034a56b2ac0cb..ac438f26b503e 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -84,7 +84,7 @@ Other Enhancements - :meth:`Series.nlargest`, :meth:`Series.nsmallest`, :meth:`DataFrame.nlargest`, and :meth:`DataFrame.nsmallest` now accept the value ``"all"`` for the ``keep`` argument. This keeps all ties for the nth largest/smallest value (:issue:`16818`) - :class:`IntervalIndex` has gained the :meth:`~IntervalIndex.set_closed` method to change the existing ``closed`` value (:issue:`21670`) - :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) -- +- Changed DatetimeIndex.time to also return timezone information. Mainly undid changes from :issue:`21821. (:issue:`21358) .. _whatsnew_0240.api_breaking: From 6e159422d9f071eb825d454aa0006d88c29a0265 Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 14:28:39 -0400 Subject: [PATCH 3/8] Added comment documenting changed test case --- doc/source/whatsnew/v0.24.0.txt | 2 +- pandas/tests/indexes/datetimes/test_timezones.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index ac438f26b503e..0a37fc6802b3f 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -84,7 +84,7 @@ Other Enhancements - :meth:`Series.nlargest`, :meth:`Series.nsmallest`, :meth:`DataFrame.nlargest`, and :meth:`DataFrame.nsmallest` now accept the value ``"all"`` for the ``keep`` argument. This keeps all ties for the nth largest/smallest value (:issue:`16818`) - :class:`IntervalIndex` has gained the :meth:`~IntervalIndex.set_closed` method to change the existing ``closed`` value (:issue:`21670`) - :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) -- Changed DatetimeIndex.time to also return timezone information. Mainly undid changes from :issue:`21821. (:issue:`21358) +- Changed DatetimeIndex.time to also return timezone information. (:issue:`21358) .. _whatsnew_0240.api_breaking: diff --git a/pandas/tests/indexes/datetimes/test_timezones.py b/pandas/tests/indexes/datetimes/test_timezones.py index 07dc65f9cd82e..8db7beaa9f030 100644 --- a/pandas/tests/indexes/datetimes/test_timezones.py +++ b/pandas/tests/indexes/datetimes/test_timezones.py @@ -724,6 +724,7 @@ def test_date_accessor(self, dtype): ]) def test_time_accessor(self, tz): # Regression test for GH#21267 + # Changed test to account for GH#21358 expected = np.array([time(10, 20, 30, tzinfo=tz), pd.NaT]) index = DatetimeIndex(['2018-06-04 10:20:30', pd.NaT], tz=tz) From 79d222ed7c1f048e383795c0165abba1544784cb Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 14:38:34 -0400 Subject: [PATCH 4/8] Updated timeseries.rst to reflect the changes made --- doc/source/timeseries.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/timeseries.rst b/doc/source/timeseries.rst index 9e01296d9c9c7..d5824ee2283ea 100644 --- a/doc/source/timeseries.rst +++ b/doc/source/timeseries.rst @@ -723,7 +723,7 @@ There are several time/date properties that one can access from ``Timestamp`` or microsecond,"The microseconds of the datetime" nanosecond,"The nanoseconds of the datetime" date,"Returns datetime.date (does not contain timezone information)" - time,"Returns datetime.time (does not contain timezone information)" + time,"Returns datetime.time (contains timezone information)" dayofyear,"The ordinal day of year" weekofyear,"The week ordinal of the year" week,"The week ordinal of the year" From 6f015a01d3662382d568e3f7c9e1907f702c6717 Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 14:52:31 -0400 Subject: [PATCH 5/8] Fixed trailing whitespace issue --- pandas/tests/indexes/datetimes/test_timezones.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pandas/tests/indexes/datetimes/test_timezones.py b/pandas/tests/indexes/datetimes/test_timezones.py index 8db7beaa9f030..6f5ed365c55af 100644 --- a/pandas/tests/indexes/datetimes/test_timezones.py +++ b/pandas/tests/indexes/datetimes/test_timezones.py @@ -719,7 +719,7 @@ def test_date_accessor(self, dtype): tm.assert_numpy_array_equal(result, expected) @pytest.mark.parametrize("tz", [ - None, pytz.timezone('CET'), pytz.timezone('EST'), + None, pytz.timezone('CET'), pytz.timezone('EST'), pytz.timezone('UTC') ]) def test_time_accessor(self, tz): From 7bd8d4331204378a5d22f8926a49d3ae5ef87ab5 Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 15:48:30 -0400 Subject: [PATCH 6/8] Added fixes to the whatsnew page --- doc/source/whatsnew/v0.24.0.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/doc/source/whatsnew/v0.24.0.txt b/doc/source/whatsnew/v0.24.0.txt index 0a37fc6802b3f..a67eef11649c2 100644 --- a/doc/source/whatsnew/v0.24.0.txt +++ b/doc/source/whatsnew/v0.24.0.txt @@ -84,7 +84,7 @@ Other Enhancements - :meth:`Series.nlargest`, :meth:`Series.nsmallest`, :meth:`DataFrame.nlargest`, and :meth:`DataFrame.nsmallest` now accept the value ``"all"`` for the ``keep`` argument. This keeps all ties for the nth largest/smallest value (:issue:`16818`) - :class:`IntervalIndex` has gained the :meth:`~IntervalIndex.set_closed` method to change the existing ``closed`` value (:issue:`21670`) - :func:`~DataFrame.to_csv` and :func:`~DataFrame.to_json` now support ``compression='infer'`` to infer compression based on filename (:issue:`15008`) -- Changed DatetimeIndex.time to also return timezone information. (:issue:`21358) +- :attr:`DatetimeIndex.time` now also returns timezone information. (:issue:`21358`) .. _whatsnew_0240.api_breaking: From 3a065436201082ffd58e1ca6a6434a67d8ffbd33 Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 16:29:43 -0400 Subject: [PATCH 7/8] Added extra comments to the datetimes.time property --- pandas/core/arrays/datetimes.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index bf229bcc54159..e7a676bf7c088 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -576,6 +576,8 @@ def day_name(self, locale=None): def time(self): """ Returns numpy array of datetime.time. The time part of the Timestamps. + Time returned is in local time, and contains associated timezone + information. """ return tslib.ints_to_pydatetime(self.asi8, self.tz, box="time") From b7e29cf920777df111a65788ebc519d10fd32c94 Mon Sep 17 00:00:00 2001 From: jequinon Date: Wed, 11 Jul 2018 16:56:53 -0400 Subject: [PATCH 8/8] Clarified the datetimes.time property comment --- pandas/core/arrays/datetimes.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pandas/core/arrays/datetimes.py b/pandas/core/arrays/datetimes.py index e7a676bf7c088..a6521b8e16ac8 100644 --- a/pandas/core/arrays/datetimes.py +++ b/pandas/core/arrays/datetimes.py @@ -576,8 +576,7 @@ def day_name(self, locale=None): def time(self): """ Returns numpy array of datetime.time. The time part of the Timestamps. - Time returned is in local time, and contains associated timezone - information. + Time returned is in local time with associated timezone information. """ return tslib.ints_to_pydatetime(self.asi8, self.tz, box="time")