Skip to content

Commit 7828999

Browse files
jbrockmendelmliu08
authored andcommitted
BUG: rendering dt64tz values with non-pytz (pandas-dev#49684)
* BUG: rendering dt64tz values with non-pytz * GH ref * py38 compat * compat for no-tzdata
1 parent cbdcfea commit 7828999

File tree

4 files changed

+44
-3
lines changed

4 files changed

+44
-3
lines changed

doc/source/whatsnew/v2.0.0.rst

+2
Original file line numberDiff line numberDiff line change
@@ -613,6 +613,8 @@ Datetimelike
613613
- Bug in :class:`DatetimeIndex` constructor failing to raise when ``tz=None`` is explicitly specified in conjunction with timezone-aware ``dtype`` or data (:issue:`48659`)
614614
- Bug in subtracting a ``datetime`` scalar from :class:`DatetimeIndex` failing to retain the original ``freq`` attribute (:issue:`48818`)
615615
- Bug in ``pandas.tseries.holiday.Holiday`` where a half-open date interval causes inconsistent return types from :meth:`USFederalHolidayCalendar.holidays` (:issue:`49075`)
616+
- Bug in rendering :class:`DatetimeIndex` and :class:`Series` and :class:`DataFrame` with timezone-aware dtypes with ``dateutil`` or ``zoneinfo`` timezones near daylight-savings transitions (:issue:`49684`)
617+
-
616618

617619
Timedelta
618620
^^^^^^^^^

pandas/_libs/tslibs/vectorized.pyi

-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ def get_resolution(
3333
def ints_to_pydatetime(
3434
arr: npt.NDArray[np.int64],
3535
tz: tzinfo | None = ...,
36-
fold: bool = ...,
3736
box: str = ...,
3837
reso: int = ..., # NPY_DATETIMEUNIT
3938
) -> npt.NDArray[np.object_]: ...

pandas/_libs/tslibs/vectorized.pyx

+2-2
Original file line numberDiff line numberDiff line change
@@ -94,7 +94,6 @@ def tz_convert_from_utc(ndarray stamps, tzinfo tz, NPY_DATETIMEUNIT reso=NPY_FR_
9494
def ints_to_pydatetime(
9595
ndarray stamps,
9696
tzinfo tz=None,
97-
bint fold=False,
9897
str box="datetime",
9998
NPY_DATETIMEUNIT reso=NPY_FR_ns,
10099
) -> np.ndarray:
@@ -136,6 +135,7 @@ def ints_to_pydatetime(
136135
tzinfo new_tz
137136
bint use_date = False, use_ts = False, use_pydt = False
138137
object res_val
138+
bint fold = 0
139139

140140
# Note that `result` (and thus `result_flat`) is C-order and
141141
# `it` iterates C-order as well, so the iteration matches
@@ -168,7 +168,7 @@ def ints_to_pydatetime(
168168

169169
else:
170170

171-
local_val = info.utc_val_to_local_val(utc_val, &pos)
171+
local_val = info.utc_val_to_local_val(utc_val, &pos, &fold)
172172
if info.use_pytz:
173173
# find right representation of dst etc in pytz timezone
174174
new_tz = tz._tzinfos[tz._transition_info[pos]]

pandas/tests/arrays/test_datetimes.py

+40
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,11 @@
44
from datetime import timedelta
55
import operator
66

7+
try:
8+
from zoneinfo import ZoneInfo
9+
except ImportError:
10+
ZoneInfo = None
11+
712
import numpy as np
813
import pytest
914

@@ -706,3 +711,38 @@ def test_tz_localize_t2d(self):
706711

707712
roundtrip = expected.tz_localize("US/Pacific")
708713
tm.assert_datetime_array_equal(roundtrip, dta)
714+
715+
easts = ["US/Eastern", "dateutil/US/Eastern"]
716+
if ZoneInfo is not None:
717+
try:
718+
easts.append(ZoneInfo("US/Eastern"))
719+
except KeyError:
720+
# No tzdata
721+
pass
722+
723+
@pytest.mark.parametrize("tz", easts)
724+
def test_iter_zoneinfo_fold(self, tz):
725+
# GH#49684
726+
utc_vals = np.array(
727+
[1320552000, 1320555600, 1320559200, 1320562800], dtype=np.int64
728+
)
729+
utc_vals *= 1_000_000_000
730+
731+
dta = DatetimeArray(utc_vals).tz_localize("UTC").tz_convert(tz)
732+
733+
left = dta[2]
734+
right = list(dta)[2]
735+
assert str(left) == str(right)
736+
# previously there was a bug where with non-pytz right would be
737+
# Timestamp('2011-11-06 01:00:00-0400', tz='US/Eastern')
738+
# while left would be
739+
# Timestamp('2011-11-06 01:00:00-0500', tz='US/Eastern')
740+
# The .value's would match (so they would compare as equal),
741+
# but the folds would not
742+
assert left.utcoffset() == right.utcoffset()
743+
744+
# The same bug in ints_to_pydatetime affected .astype, so we test
745+
# that here.
746+
right2 = dta.astype(object)[2]
747+
assert str(left) == str(right2)
748+
assert left.utcoffset() == right2.utcoffset()

0 commit comments

Comments
 (0)