diff --git a/pandas/_libs/tslibs/tzconversion.pxd b/pandas/_libs/tslibs/tzconversion.pxd index 1990afd77a8fb..3666d00707ac8 100644 --- a/pandas/_libs/tslibs/tzconversion.pxd +++ b/pandas/_libs/tslibs/tzconversion.pxd @@ -2,7 +2,9 @@ from cpython.datetime cimport tzinfo from numpy cimport int64_t -cdef int64_t tz_convert_utc_to_tzlocal(int64_t utc_val, tzinfo tz, bint* fold=*) +cdef int64_t tz_convert_utc_to_tzlocal( + int64_t utc_val, tzinfo tz, bint* fold=* +) except? -1 cpdef int64_t tz_convert_from_utc_single(int64_t val, tzinfo tz) cdef int64_t tz_localize_to_utc_single( int64_t val, tzinfo tz, object ambiguous=*, object nonexistent=* diff --git a/pandas/_libs/tslibs/tzconversion.pyx b/pandas/_libs/tslibs/tzconversion.pyx index 4a3fac1954ab7..f08a86b1262e6 100644 --- a/pandas/_libs/tslibs/tzconversion.pyx +++ b/pandas/_libs/tslibs/tzconversion.pyx @@ -355,7 +355,9 @@ cdef inline str _render_tstamp(int64_t val): # ---------------------------------------------------------------------- # Timezone Conversion -cdef int64_t tz_convert_utc_to_tzlocal(int64_t utc_val, tzinfo tz, bint* fold=NULL): +cdef int64_t tz_convert_utc_to_tzlocal( + int64_t utc_val, tzinfo tz, bint* fold=NULL +) except? -1: """ Parameters ---------- @@ -549,8 +551,10 @@ cdef inline int64_t _tzlocal_get_offset_components(int64_t val, tzinfo tz, return int(td.total_seconds() * 1_000_000_000) +# OSError may be thrown by tzlocal on windows at or close to 1970-01-01 +# see https://github.com/pandas-dev/pandas/pull/37591#issuecomment-720628241 cdef int64_t _tz_convert_tzlocal_utc(int64_t val, tzinfo tz, bint to_utc=True, - bint* fold=NULL): + bint* fold=NULL) except? -1: """ Convert the i8 representation of a datetime from a tzlocal timezone to UTC, or vice-versa. diff --git a/pandas/tests/frame/test_reductions.py b/pandas/tests/frame/test_reductions.py index fbb51b70d34fd..374d185f45844 100644 --- a/pandas/tests/frame/test_reductions.py +++ b/pandas/tests/frame/test_reductions.py @@ -1,9 +1,11 @@ from datetime import timedelta from decimal import Decimal +from dateutil.tz import tzlocal import numpy as np import pytest +from pandas.compat import is_platform_windows import pandas.util._test_decorators as td import pandas as pd @@ -1172,6 +1174,12 @@ def test_min_max_dt64_with_NaT(self): def test_min_max_dt64_with_NaT_skipna_false(self, tz_naive_fixture): # GH#36907 tz = tz_naive_fixture + if isinstance(tz, tzlocal) and is_platform_windows(): + pytest.xfail( + reason="GH#37659 OSError raised within tzlocal bc Windows " + "chokes in times before 1970-01-01" + ) + df = DataFrame( { "a": [ diff --git a/pandas/tests/indexes/datetimes/test_ops.py b/pandas/tests/indexes/datetimes/test_ops.py index 1d64fde103e9e..0359ee17f87c5 100644 --- a/pandas/tests/indexes/datetimes/test_ops.py +++ b/pandas/tests/indexes/datetimes/test_ops.py @@ -1,8 +1,11 @@ from datetime import datetime +from dateutil.tz import tzlocal import numpy as np import pytest +from pandas.compat import IS64 + import pandas as pd from pandas import ( DateOffset, @@ -106,24 +109,27 @@ def test_repeat(self, tz_naive_fixture): with pytest.raises(ValueError, match=msg): np.repeat(rng, reps, axis=1) - def test_resolution(self, tz_naive_fixture): + @pytest.mark.parametrize( + "freq,expected", + [ + ("A", "day"), + ("Q", "day"), + ("M", "day"), + ("D", "day"), + ("H", "hour"), + ("T", "minute"), + ("S", "second"), + ("L", "millisecond"), + ("U", "microsecond"), + ], + ) + def test_resolution(self, tz_naive_fixture, freq, expected): tz = tz_naive_fixture - for freq, expected in zip( - ["A", "Q", "M", "D", "H", "T", "S", "L", "U"], - [ - "day", - "day", - "day", - "day", - "hour", - "minute", - "second", - "millisecond", - "microsecond", - ], - ): - idx = pd.date_range(start="2013-04-01", periods=30, freq=freq, tz=tz) - assert idx.resolution == expected + if freq == "A" and not IS64 and isinstance(tz, tzlocal): + pytest.xfail(reason="OverflowError inside tzlocal past 2038") + + idx = pd.date_range(start="2013-04-01", periods=30, freq=freq, tz=tz) + assert idx.resolution == expected def test_value_counts_unique(self, tz_naive_fixture): tz = tz_naive_fixture diff --git a/pandas/tests/tseries/offsets/test_offsets.py b/pandas/tests/tseries/offsets/test_offsets.py index fba123e47feb2..fca1316493e85 100644 --- a/pandas/tests/tseries/offsets/test_offsets.py +++ b/pandas/tests/tseries/offsets/test_offsets.py @@ -1,6 +1,7 @@ from datetime import date, datetime, time as dt_time, timedelta from typing import Dict, List, Optional, Tuple, Type +from dateutil.tz import tzlocal import numpy as np import pytest @@ -14,6 +15,7 @@ import pandas._libs.tslibs.offsets as liboffsets from pandas._libs.tslibs.offsets import ApplyTypeError, _get_offset, _offset_map from pandas._libs.tslibs.period import INVALID_FREQ_ERR_MSG +from pandas.compat import IS64 from pandas.compat.numpy import np_datetime64_compat from pandas.errors import PerformanceWarning @@ -129,6 +131,8 @@ def test_apply_out_of_range(self, tz_naive_fixture): tz = tz_naive_fixture if self._offset is None: return + if isinstance(tz, tzlocal) and not IS64: + pytest.xfail(reason="OverflowError inside tzlocal past 2038") # try to create an out-of-bounds result timestamp; if we can't create # the offset skip