Files
sirh/venv/lib/python3.12/site-packages/pandas/tests/tslibs/test_timezones.py
2026-04-29 11:52:03 +02:00

194 lines
5.5 KiB
Python

from datetime import (
datetime,
timedelta,
timezone,
)
import subprocess
import sys
import textwrap
import dateutil.tz
import pytest
from pandas._libs.tslibs import (
conversion,
timezones,
)
from pandas.compat import is_platform_windows
from pandas import Timestamp
@pytest.mark.single_cpu
def test_no_timezone_data():
# https://github.com/pandas-dev/pandas/pull/63335
# Test error message when timezone data is not available.
msg = "'No time zone found with key Europe/Brussels'"
code = textwrap.dedent(
f"""\
import sys, zoneinfo, pandas as pd
sys.modules['tzdata'] = None
zoneinfo.reset_tzpath(['/path/to/nowhere'])
try:
pd.to_datetime('2012-01-01').tz_localize('Europe/Brussels')
except zoneinfo.ZoneInfoNotFoundError as err:
assert str(err) == "{msg}"
"""
)
subprocess.check_call([sys.executable, "-c", code])
def test_is_utc(utc_fixture):
tz = timezones.maybe_get_tz(utc_fixture)
assert timezones.is_utc(tz)
def test_cache_keys_are_distinct_for_pytz_vs_dateutil():
pytz = pytest.importorskip("pytz")
for tz_name in pytz.common_timezones:
tz_p = timezones.maybe_get_tz(tz_name)
tz_d = timezones.maybe_get_tz("dateutil/" + tz_name)
if tz_d is None:
pytest.skip(tz_name + ": dateutil does not know about this one")
if not (tz_name == "UTC" and is_platform_windows()):
# they both end up as tzwin("UTC") on windows
assert timezones._p_tz_cache_key(tz_p) != timezones._p_tz_cache_key(tz_d)
def test_tzlocal_repr():
# see gh-13583
ts = Timestamp("2011-01-01", tz=dateutil.tz.tzlocal())
assert ts.tz == dateutil.tz.tzlocal()
assert "tz='tzlocal()')" in repr(ts)
def test_tzlocal_maybe_get_tz():
# see gh-13583
tz = timezones.maybe_get_tz("tzlocal()")
assert tz == dateutil.tz.tzlocal()
def test_tzlocal_offset():
# see gh-13583
#
# Get offset using normal datetime for test.
ts = Timestamp("2011-01-01", tz=dateutil.tz.tzlocal()).as_unit("s")
offset = dateutil.tz.tzlocal().utcoffset(datetime(2011, 1, 1))
offset = offset.total_seconds()
assert ts._value + offset == Timestamp("2011-01-01").as_unit("s")._value
def test_tzlocal_is_not_utc():
# even if the machine running the test is localized to UTC
tz = dateutil.tz.tzlocal()
assert not timezones.is_utc(tz)
assert not timezones.tz_compare(tz, dateutil.tz.tzutc())
def test_tz_compare_utc(utc_fixture, utc_fixture2):
tz = timezones.maybe_get_tz(utc_fixture)
tz2 = timezones.maybe_get_tz(utc_fixture2)
assert timezones.tz_compare(tz, tz2)
@pytest.fixture(
params=[
("pytz/US/Eastern", lambda tz, x: tz.localize(x)),
(dateutil.tz.gettz("US/Eastern"), lambda tz, x: x.replace(tzinfo=tz)),
]
)
def infer_setup(request):
eastern, localize = request.param
if isinstance(eastern, str) and eastern.startswith("pytz/"):
pytz = pytest.importorskip("pytz")
eastern = pytz.timezone(eastern.removeprefix("pytz/"))
start_naive = datetime(2001, 1, 1)
end_naive = datetime(2009, 1, 1)
start = localize(eastern, start_naive)
end = localize(eastern, end_naive)
return eastern, localize, start, end, start_naive, end_naive
def test_infer_tz_compat(infer_setup):
eastern, _, start, end, start_naive, end_naive = infer_setup
assert (
timezones.infer_tzinfo(start, end)
is conversion.localize_pydatetime(start_naive, eastern).tzinfo
)
assert (
timezones.infer_tzinfo(start, None)
is conversion.localize_pydatetime(start_naive, eastern).tzinfo
)
assert (
timezones.infer_tzinfo(None, end)
is conversion.localize_pydatetime(end_naive, eastern).tzinfo
)
def test_infer_tz_utc_localize(infer_setup):
_, _, start, end, start_naive, end_naive = infer_setup
utc = timezone.utc
start = start_naive.astimezone(utc)
end = end_naive.astimezone(utc)
assert timezones.infer_tzinfo(start, end) is utc
@pytest.mark.parametrize("ordered", [True, False])
def test_infer_tz_mismatch(infer_setup, ordered):
eastern, _, _, _, start_naive, end_naive = infer_setup
msg = "Inputs must both have the same timezone"
utc = timezone.utc
start = start_naive.astimezone(utc)
end = conversion.localize_pydatetime(end_naive, eastern)
args = (start, end) if ordered else (end, start)
with pytest.raises(AssertionError, match=msg):
timezones.infer_tzinfo(*args)
def test_maybe_get_tz_invalid_types():
with pytest.raises(TypeError, match="<class 'float'>"):
timezones.maybe_get_tz(44.0)
with pytest.raises(TypeError, match="<class 'module'>"):
timezones.maybe_get_tz(pytest)
msg = "<class 'pandas.Timestamp'>"
with pytest.raises(TypeError, match=msg):
timezones.maybe_get_tz(Timestamp("2021-01-01", tz="UTC"))
def test_maybe_get_tz_offset_only():
# see gh-36004
# timezone.utc
tz = timezones.maybe_get_tz(timezone.utc)
assert tz == timezone(timedelta(hours=0, minutes=0))
# without UTC+- prefix
tz = timezones.maybe_get_tz("+01:15")
assert tz == timezone(timedelta(hours=1, minutes=15))
tz = timezones.maybe_get_tz("-01:15")
assert tz == timezone(-timedelta(hours=1, minutes=15))
# with UTC+- prefix
tz = timezones.maybe_get_tz("UTC+02:45")
assert tz == timezone(timedelta(hours=2, minutes=45))
tz = timezones.maybe_get_tz("UTC-02:45")
assert tz == timezone(-timedelta(hours=2, minutes=45))