Skip to content

Commit 31ab5a3

Browse files
authored
chore: use zoneinfo instead of pytz (#107)
# Description Closes #98 by preferring ` backports.zoneinfo` to `pytz` for py3.8
1 parent 41dd5a4 commit 31ab5a3

File tree

6 files changed

+21
-36
lines changed

6 files changed

+21
-36
lines changed

dirty_equals/_datetime.py

Lines changed: 8 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
from __future__ import annotations as _annotations
22

3+
import sys
34
from datetime import date, datetime, timedelta, timezone, tzinfo
4-
from typing import TYPE_CHECKING, Any
5+
from typing import Any
56

67
from ._numeric import IsNumeric
78
from ._utils import Omit
89

9-
if TYPE_CHECKING:
10+
if sys.version_info >= (3, 9):
1011
from zoneinfo import ZoneInfo
12+
else:
13+
# This code block is due to a typing issue with backports.zoneinfo package:
14+
# https://github.com/pganssle/zoneinfo/issues/125
15+
from backports.zoneinfo._zoneinfo import ZoneInfo
1116

1217

1318
class IsDatetime(IsNumeric[datetime]):
@@ -122,24 +127,6 @@ def approx_equals(self, other: datetime, delta: timedelta) -> bool:
122127
return True
123128

124129

125-
def _zoneinfo(tz: str) -> ZoneInfo:
126-
"""
127-
Instantiate a `ZoneInfo` object from a string, falling back to `pytz.timezone` when `ZoneInfo` is not available
128-
(most likely on Python 3.8 and webassembly).
129-
"""
130-
try:
131-
from zoneinfo import ZoneInfo
132-
except ImportError:
133-
try:
134-
import pytz
135-
except ImportError as e:
136-
raise ImportError('`pytz` or `zoneinfo` required for tz handling') from e
137-
else:
138-
return pytz.timezone(tz) # type: ignore[return-value]
139-
else:
140-
return ZoneInfo(tz)
141-
142-
143130
class IsNow(IsDatetime):
144131
"""
145132
Check if a datetime is close to now, this is similar to `IsDatetime(approx=datetime.now())`,
@@ -185,7 +172,7 @@ def __init__(
185172
```
186173
"""
187174
if isinstance(tz, str):
188-
tz = _zoneinfo(tz)
175+
tz = ZoneInfo(tz)
189176

190177
self.tz = tz
191178

pyproject.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ classifiers = [
3737
]
3838
requires-python = '>=3.8'
3939
dependencies = [
40-
'pytz>=2021.3;python_version<"3.9"',
40+
'backports.zoneinfo;python_version<"3.9"',
4141
]
4242
optional-dependencies = {pydantic = ['pydantic>=2.4.2'] }
4343
dynamic = ['version']

requirements/linting.txt

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,6 @@ pydantic-core==2.20.1
1616
# via pydantic
1717
ruff==0.5.7
1818
# via -r requirements/linting.in
19-
types-pytz==2024.1.0.20240417
20-
# via -r requirements/linting.in
2119
typing-extensions==4.12.2
2220
# via
2321
# mypy

requirements/tests.in

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,4 @@ pytest
44
pytest-mock
55
pytest-pretty
66
pytest-examples
7-
pytz
7+
backports.zoneinfo;python_version<"3.9"

requirements/tests.txt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ pytest-mock==3.14.0
4545
# via -r requirements/tests.in
4646
pytest-pretty==1.2.0
4747
# via -r requirements/tests.in
48-
pytz==2024.1
48+
backports.zoneinfo;python_version<"3.9"
4949
# via -r requirements/tests.in
5050
rich==13.7.1
5151
# via pytest-pretty

tests/test_datetime.py

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,17 @@
1+
import sys
12
from datetime import date, datetime, timedelta, timezone
23
from unittest.mock import Mock
34

45
import pytest
5-
import pytz
66

77
from dirty_equals import IsDate, IsDatetime, IsNow, IsToday
88

9-
try:
9+
if sys.version_info >= (3, 9):
1010
from zoneinfo import ZoneInfo
11-
except ImportError:
12-
ZoneInfo = None
11+
else:
12+
# This code block is due to a typing issue with backports.zoneinfo package:
13+
# https://github.com/pganssle/zoneinfo/issues/125
14+
from backports.zoneinfo._zoneinfo import ZoneInfo
1315

1416

1517
@pytest.mark.parametrize(
@@ -61,16 +63,14 @@
6163
id='tz-1-hour',
6264
),
6365
pytest.param(
64-
pytz.timezone('Europe/London').localize(datetime(2022, 2, 15, 15, 15)),
65-
IsDatetime(
66-
approx=pytz.timezone('America/New_York').localize(datetime(2022, 2, 15, 10, 15)), enforce_tz=False
67-
),
66+
datetime(2022, 2, 15, 15, 15, tzinfo=ZoneInfo('Europe/London')),
67+
IsDatetime(approx=datetime(2022, 2, 15, 10, 15, tzinfo=ZoneInfo('America/New_York')), enforce_tz=False),
6868
True,
6969
id='tz-both-tz',
7070
),
7171
pytest.param(
72-
pytz.timezone('Europe/London').localize(datetime(2022, 2, 15, 15, 15)),
73-
IsDatetime(approx=pytz.timezone('America/New_York').localize(datetime(2022, 2, 15, 10, 15))),
72+
datetime(2022, 2, 15, 15, 15, tzinfo=ZoneInfo('Europe/London')),
73+
IsDatetime(approx=datetime(2022, 2, 15, 10, 15, tzinfo=ZoneInfo('America/New_York'))),
7474
False,
7575
id='tz-both-tz-different',
7676
),

0 commit comments

Comments
 (0)