-
-
Notifications
You must be signed in to change notification settings - Fork 18.4k
BUG: Using DatetimeIndex.date with timezone returns incorrect date #2… #21281
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
Conversation
pandas/core/indexes/datetimes.py
Outdated
@@ -2040,7 +2040,7 @@ def date(self): | |||
Returns numpy array of python datetime.date objects (namely, the date | |||
part of Timestamps without timezone information). | |||
""" | |||
return libts.ints_to_pydatetime(self.normalize().asi8, box="date") | |||
return libts.ints_to_pydatetime(self.asi8, box="date") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this needs to be self._local_timestamps()
instead of self.asi8
since those are essentially epoch (UTC) timestamps and we want to return local values.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the suggestion. That might be it.
@@ -27,6 +27,21 @@ def test_roundtrip_pickle_with_tz(self): | |||
unpickled = tm.round_trip_pickle(index) | |||
tm.assert_index_equal(index, unpickled) | |||
|
|||
def test_date_accessor_with_tz(self): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of 2 separate tests, you can have one test pytest.mark.parameterize
over the timezone aware and naive data. (e.g. dtype='datetime64[ns, CET]''
and dtype=None
)
Codecov Report
@@ Coverage Diff @@
## master #21281 +/- ##
==========================================
+ Coverage 91.85% 91.85% +<.01%
==========================================
Files 153 153
Lines 49549 49555 +6
==========================================
+ Hits 45512 45518 +6
Misses 4037 4037
Continue to review full report at Codecov.
|
ASV for this commit:
|
pandas/core/indexes/datetimes.py
Outdated
@@ -2040,7 +2040,11 @@ def date(self): | |||
Returns numpy array of python datetime.date objects (namely, the date | |||
part of Timestamps without timezone information). | |||
""" | |||
return libts.ints_to_pydatetime(self.normalize().asi8, box="date") | |||
if (self.tz is None): | |||
return libts.ints_to_pydatetime(self.normalize().asi8, box="date") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need the .normalize()
calls here? I think ints_to_pydatetime
will strip the time information away when constructing the date
]) | ||
def test_date_accessor(self, test_input): | ||
# GH 21230 | ||
from datetime import date |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks like this is imported at the top already
# GH 21230 | ||
from datetime import date | ||
|
||
assert test_input.date == np.array(date(2013, 1, 24)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Use tm.assert_numpy_array_equal
here.
@@ -27,6 +27,18 @@ def test_roundtrip_pickle_with_tz(self): | |||
unpickled = tm.round_trip_pickle(index) | |||
tm.assert_index_equal(index, unpickled) | |||
|
|||
@pytest.mark.parametrize("test_input", [ | |||
DatetimeIndex(['2013-01-24 15:01:00']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead, you could leave the DatetimeIndex
construction in the test, and parametrize over the dtypes and pass that into the constructor.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR!
Can you do a similar change for time
attribute (just above date
in the code) ?
Then it would also close #21267 |
Sure. There's some discussion in #21267 about whether |
I think converting back to the 0.22 behaviour is the best for now (which I think is no timezone in the output?) We can still later discuss if we want to add the timezone or not. |
@jorisvandenbossche regarding my comment (#21267 (comment)), it looks like the |
pandas/core/indexes/datetimes.py
Outdated
@@ -2040,7 +2040,11 @@ def date(self): | |||
Returns numpy array of python datetime.date objects (namely, the date | |||
part of Timestamps without timezone information). | |||
""" | |||
return libts.ints_to_pydatetime(self.normalize().asi8, box="date") | |||
if (self.tz is None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
prob need
if self.tz is not None and self.tz is not utc
also write it more like
# add a comment here about tz conversions
if self.tz is not None and self.tz is not utc:
stamps = self.asi8
else:
stamps = self._local_timestamps()
return libts.init_to_pytdatetime(stamps, box="date")
# GH 21230 | ||
|
||
index = DatetimeIndex(['2013-01-24 15:01:00'], dtype=dtype) | ||
tm.assert_numpy_array_equal(index.date, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
use
result =
expected =
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can you add another date that is not ambiguous (e.g. its on the same date regardless of tz)
can you add a NaT as well
@@ -27,6 +27,17 @@ def test_roundtrip_pickle_with_tz(self): | |||
unpickled = tm.round_trip_pickle(index) | |||
tm.assert_index_equal(index, unpickled) | |||
|
|||
@pytest.mark.parametrize("dtype", [ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this needs to go in test_timezones
(same subdir)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
place it near other tests that look at .date
doc/source/whatsnew/v0.23.1.txt
Outdated
@@ -85,7 +85,7 @@ Indexing | |||
- Bug in :meth:`Series.reset_index` where appropriate error was not raised with an invalid level name (:issue:`20925`) | |||
- Bug in :func:`interval_range` when ``start``/``periods`` or ``end``/``periods`` are specified with float ``start`` or ``end`` (:issue:`21161`) | |||
- Bug in :meth:`MultiIndex.set_names` where error raised for a ``MultiIndex`` with ``nlevels == 1`` (:issue:`21149`) | |||
- | |||
- Bug in :attr:`DatetimeIndex.date` where an incorrect date is returned when the input date has a timezone (:issue:`21230`) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this should be non-UTC timezone
@jorisvandenbossche @mroeschke @jreback For #21267, it seems that whether the timezone should be returned still needs to be discussed. Is it ok if I change the behavior of |
looking at this again - both .date and .time should be naive i think (and .date already is) so ok to change .time back to naive mention in docs that these are local (naive) date/times that are returned pls create an issue about this for discussion as well (eg to in future make these tz-aware) |
expected = np.array([date(2018, 6, 4), pd.NaT], ndmin=1) | ||
|
||
index = DatetimeIndex(['2018-06-04 10:00:00', pd.NaT], dtype=dtype) | ||
result = index.date |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
can u also test .time here
No, adding the timezone was unintended, and is inconsistent with how Timestamp itself works, and inconsistent with standard library (they both return naive local time). |
@jreback sorry, missed the update of your comment. So yes, then we agree! |
]) | ||
def test_date_accessor(self, dtype): | ||
# Regression test for GH#21230 | ||
expected = np.array([date(2018, 6, 4), pd.NaT], ndmin=1) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is the ndmin=1
needed here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I needed it to avoid a shape of (1,) when creating a numpy array with only 1 element. I'll remove it now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
minor comment, looks good to me, thanks!
Is there any way to trigger a re-build on CircleCI? That build failed with this error:
|
@tmnhat2001 Thanks a lot! |
Thanks everyone. |
…andas-dev#21281) * BUG: Using DatetimeIndex.date with timezone returns incorrect date pandas-dev#21230 * Fix bug where DTI.time returns a tz-aware Time instead of tz-naive pandas-dev#21267 (cherry picked from commit a363e1a)
…andas-dev#21281) * BUG: Using DatetimeIndex.date with timezone returns incorrect date pandas-dev#21230 * Fix bug where DTI.time returns a tz-aware Time instead of tz-naive pandas-dev#21267
git diff upstream/master -u -- "*.py" | flake8 --diff
Added 2 tests for DatetimeIndex.date in tests/indexes/datetimes/test_datetime.py. Please let me know if I should move them somewhere else.