Skip to content

Commit 82f263a

Browse files
committed
Use vectorized searchsorted and tests.
1 parent a1ed5a5 commit 82f263a

File tree

2 files changed

+53
-11
lines changed

2 files changed

+53
-11
lines changed

pandas/tseries/tests/test_timezones.py

+40
Original file line numberDiff line numberDiff line change
@@ -902,6 +902,46 @@ def test_utc_with_system_utc(self):
902902
# check that the time hasn't changed.
903903
self.assertEqual(ts, ts.tz_convert(dateutil.tz.tzutc()))
904904

905+
def test_tslib_tz_convert_hour_overflow_dst_bug(self):
906+
# Regression test for:
907+
# https://github.com/pydata/pandas/issues/13306
908+
909+
# sorted case US/Eastern -> UTC
910+
ts = ['2008-05-12 09:50:00-04:00',
911+
'2008-12-12 09:50:35-05:00',
912+
'2009-05-12 09:50:32-04:00']
913+
tt = to_datetime(ts).tz_localize('US/Eastern')
914+
ut = tt.tz_convert('UTC')
915+
expected = np.array([17, 19, 17], dtype=np.int32)
916+
self.assert_numpy_array_equal(ut.hour, expected)
917+
918+
# sorted case UTC -> US/Eastern
919+
ts = ['2008-05-12 17:50:00',
920+
'2008-12-12 19:50:35',
921+
'2009-05-12 17:50:32']
922+
tt = to_datetime(ts).tz_localize('UTC')
923+
ut = tt.tz_convert('US/Eastern')
924+
expected = np.array([13, 14, 13], dtype=np.int32)
925+
self.assert_numpy_array_equal(ut.hour, expected)
926+
927+
# unsorted case US/Eastern -> UTC
928+
ts = ['2008-05-12 09:50:00-04:00',
929+
'2008-12-12 09:50:35-05:00',
930+
'2008-05-12 09:50:32-04:00']
931+
tt = to_datetime(ts).tz_localize('US/Eastern')
932+
ut = tt.tz_convert('UTC')
933+
expected = np.array([17, 19, 17], dtype=np.int32)
934+
self.assert_numpy_array_equal(ut.hour, expected)
935+
936+
# unsorted case UTC -> US/Eastern
937+
ts = ['2008-05-12 17:50:00',
938+
'2008-12-12 19:50:35',
939+
'2008-05-12 17:50:32']
940+
tt = to_datetime(ts).tz_localize('UTC')
941+
ut = tt.tz_convert('US/Eastern')
942+
expected = np.array([13, 14, 13], dtype=np.int32)
943+
self.assert_numpy_array_equal(ut.hour, expected)
944+
905945
def test_tslib_tz_convert_trans_pos_plus_1__bug(self):
906946
# Regression test for tslib.tz_convert(vals, tz1, tz2).
907947
# See https://github.com/pydata/pandas/issues/4496 for details.

pandas/tslib.pyx

+13-11
Original file line numberDiff line numberDiff line change
@@ -3754,8 +3754,8 @@ except:
37543754

37553755
def tz_convert(ndarray[int64_t] vals, object tz1, object tz2):
37563756
cdef:
3757-
ndarray[int64_t] utc_dates, tt, result, trans, deltas
3758-
Py_ssize_t i, pos, n = len(vals)
3757+
ndarray[int64_t] utc_dates, tt, result, trans, deltas, posn
3758+
Py_ssize_t i, j, pos, n = len(vals)
37593759
int64_t v, offset
37603760
pandas_datetimestruct dts
37613761
Py_ssize_t trans_len
@@ -3791,19 +3791,18 @@ def tz_convert(ndarray[int64_t] vals, object tz1, object tz2):
37913791
return vals
37923792

37933793
trans_len = len(trans)
3794-
pos = trans.searchsorted(tt[0]) - 1
3795-
if pos < 0:
3796-
raise ValueError('First time before start of DST info')
3797-
3798-
offset = deltas[pos]
3794+
posn = trans.searchsorted(tt, side='right')
3795+
j = 0
37993796
for i in range(n):
38003797
v = vals[i]
38013798
if v == NPY_NAT:
38023799
utc_dates[i] = NPY_NAT
38033800
else:
3804-
while pos + 1 < trans_len and v >= trans[pos + 1]:
3805-
pos += 1
3806-
offset = deltas[pos]
3801+
pos = posn[j] - 1
3802+
j = j + 1
3803+
if pos < 0:
3804+
raise ValueError('First time before start of DST info')
3805+
offset = deltas[pos]
38073806
utc_dates[i] = v - offset
38083807
else:
38093808
utc_dates = vals
@@ -3838,12 +3837,15 @@ def tz_convert(ndarray[int64_t] vals, object tz1, object tz2):
38383837
if (result==NPY_NAT).all():
38393838
return result
38403839

3840+
posn = trans.searchsorted(utc_dates[utc_dates!=NPY_NAT], side='right')
3841+
j = 0
38413842
for i in range(n):
38423843
v = utc_dates[i]
38433844
if vals[i] == NPY_NAT:
38443845
result[i] = vals[i]
38453846
else:
3846-
pos = trans.searchsorted(v, side='right') - 1
3847+
pos = posn[j] - 1
3848+
j = j + 1
38473849
if pos < 0:
38483850
raise ValueError('First time before start of DST info')
38493851
offset = deltas[pos]

0 commit comments

Comments
 (0)