From 7df81490bc5d45a480af27eb9cc57c60c603529c Mon Sep 17 00:00:00 2001 From: Sten Date: Wed, 7 Aug 2013 15:27:38 +0400 Subject: [PATCH] Fix issue #4496: tslib.tz_convert(vals, tz1, tz2) may raise an IndexError exception. --- doc/source/release.rst | 2 ++ pandas/tests/test_frame.py | 19 +++++++++++++++++++ pandas/tslib.pyx | 4 +++- 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/doc/source/release.rst b/doc/source/release.rst index 578e235b0f88b..e679fa320e1db 100644 --- a/doc/source/release.rst +++ b/doc/source/release.rst @@ -197,6 +197,8 @@ See :ref:`Internal Refactoring` - raising an invalid ``TypeError`` rather than ``ValueError`` when appending with a different block ordering (:issue:`4096`) - ``read_hdf`` was not respecting as passed ``mode`` (:issue:`4504`) + - Fixed bug in tslib.tz_convert(vals, tz1, tz2): it could raise IndexError exception while + trying to access trans[pos + 1] (:issue:`4496`) - The ``by`` argument now works correctly with the ``layout`` argument (:issue:`4102`, :issue:`4014`) in ``*.hist`` plotting methods - Fixed bug in ``PeriodIndex.map`` where using ``str`` would return the str diff --git a/pandas/tests/test_frame.py b/pandas/tests/test_frame.py index c8f87a19a5f34..517c984fa0e64 100644 --- a/pandas/tests/test_frame.py +++ b/pandas/tests/test_frame.py @@ -10587,6 +10587,25 @@ def test_consolidate_datetime64(self): assert_array_equal(df.starting.values, ser_starting.index.values) assert_array_equal(df.ending.values, ser_ending.index.values) + def test_tslib_tz_convert_trans_pos_plus_1__bug(self): + """ + Regression test for tslib.tz_convert(vals, tz1, tz2). + See https://github.com/pydata/pandas/issues/4496 for details. + """ + idx = pd.date_range(datetime(2011, 3, 26, 23), datetime(2011, 3, 27, 1), freq='1min') + idx = idx.tz_localize('UTC') + idx = idx.tz_convert('Europe/Moscow') + + test_vector = pd.Series([3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 5], dtype=int) + + hours = idx.hour + + np.testing.assert_equal(hours, test_vector.values) + def _check_bool_op(self, name, alternative, frame=None, has_skipna=True, has_bool_only=False): if frame is None: diff --git a/pandas/tslib.pyx b/pandas/tslib.pyx index 18917fdd82d1b..983d3385e8f85 100644 --- a/pandas/tslib.pyx +++ b/pandas/tslib.pyx @@ -1432,9 +1432,11 @@ def tz_convert(ndarray[int64_t] vals, object tz1, object tz2): pos -= 1 offset = deltas[pos] + cdef Py_ssize_t trans_len = len(trans) + for i in range(n): v = utc_dates[i] - if v >= trans[pos + 1]: + if (pos + 1) < trans_len and v >= trans[pos + 1]: pos += 1 offset = deltas[pos] result[i] = v + offset