Skip to content

Commit 96542a8

Browse files
committed
Add the ability to disable timezone extension
1 parent 0e971ff commit 96542a8

File tree

6 files changed

+66
-12
lines changed

6 files changed

+66
-12
lines changed

pendulum/tz/__init__.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
_tz_cache = {}
2121

2222

23-
def timezone(name): # type: (Union[str, int]) -> _Timezone
23+
def timezone(name, extended=True): # type: (Union[str, int]) -> _Timezone
2424
"""
2525
Return a Timezone instance given its name.
2626
"""
@@ -33,7 +33,7 @@ def timezone(name): # type: (Union[str, int]) -> _Timezone
3333
if name in _tz_cache:
3434
return _tz_cache[name]
3535

36-
tz = _Timezone(name)
36+
tz = _Timezone(name, extended=extended)
3737
_tz_cache[name] = tz
3838

3939
return tz

pendulum/tz/timezone.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,8 @@ class Timezone(tzinfo):
2626
>>> tz = Timezone('Europe/Paris')
2727
"""
2828

29-
def __init__(self, name): # type: (str) -> None
30-
tz = read(name)
29+
def __init__(self, name, extended=True): # type: (str) -> None
30+
tz = read(name, extend=extended)
3131

3232
self._name = name
3333
self._transitions = tz.transitions

pendulum/tz/zoneinfo/__init__.py

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,16 @@
11
from .reader import Reader
22
from .timezone import Timezone
33

4-
_reader = Reader()
54

6-
7-
def read(name): # type: (str) -> Timezone
5+
def read(name, extend=True): # type: (str) -> Timezone
86
"""
97
Read the zoneinfo structure for a given timezone name.
108
"""
11-
return _reader.read_for(name)
9+
return Reader(extend=extend).read_for(name)
1210

1311

14-
def read_file(path): # type: (str) -> Timezone:
12+
def read_file(path, extend=True): # type: (str) -> Timezone
1513
"""
1614
Read the zoneinfo structure for a given path.
1715
"""
18-
return _reader.read(path)
16+
return Reader(extend=extend).read(path)

pendulum/tz/zoneinfo/reader.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,9 @@ class Reader:
3535
Reads compiled zoneinfo TZif (\0, 2 or 3) files.
3636
"""
3737

38+
def __init__(self, extend=True): # type: (bool) -> None
39+
self._extend = extend
40+
3841
def read_for(self, timezone): # type: (str) -> Timezone
3942
"""
4043
Read the zoneinfo structure for a given timezone name.
@@ -147,7 +150,7 @@ def _parse(self, fd): # type: (...) -> Timezone
147150
Transition(0, types[0], None)
148151
)
149152

150-
return Timezone(transitions, posix_rule=trule)
153+
return Timezone(transitions, posix_rule=trule, extended=self._extend)
151154

152155
def _parse_header(self, fd): # type: (...) -> header
153156
buff = self._check_read(fd, 44)

pendulum/tz/zoneinfo/timezone.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,11 +14,13 @@ class Timezone:
1414
def __init__(self,
1515
transitions, # type: List[Transition]
1616
posix_rule=None, # type: Union[PosixTimezone, None]
17+
extended=True # type: bool
1718
):
1819
self._posix_rule = posix_rule
1920
self._transitions = transitions
2021

21-
self._extends()
22+
if extended:
23+
self._extends()
2224

2325
@property
2426
def transitions(self): # type: () -> List[Transition]

tests/tz/test_timezone.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,15 @@
1010
from ..conftest import assert_datetime
1111

1212

13+
@pytest.fixture(autouse=True)
14+
def setup():
15+
pendulum.tz._tz_cache = {}
16+
17+
yield
18+
19+
pendulum.tz._tz_cache = {}
20+
21+
1322
@pytest.mark.skipif(not PY36, reason='fold attribute only present in Python 3.6+')
1423
def test_basic_convert():
1524
dt = datetime(2016, 6, 1, 12, 34, 56, 123456, fold=1)
@@ -497,6 +506,48 @@ def test_timezones_are_extended():
497506
assert dt.dst() == timedelta()
498507

499508

509+
def test_timezones_extension_can_be_disabled():
510+
tz = pendulum.timezone('Europe/Paris', extended=False)
511+
dt = tz.convert(pendulum.naive(2134, 2, 13, 1))
512+
513+
assert_datetime(dt, 2134, 2, 13, 1)
514+
assert dt.utcoffset().total_seconds() == 3600
515+
assert dt.dst() == timedelta()
516+
517+
dt = tz.convert(
518+
pendulum.naive(2134, 3, 28, 2, 30),
519+
dst_rule=pendulum.POST_TRANSITION
520+
)
521+
522+
assert_datetime(dt, 2134, 3, 28, 2, 30)
523+
assert dt.utcoffset().total_seconds() == 3600
524+
assert dt.dst() == timedelta()
525+
526+
dt = tz.convert(pendulum.naive(2134, 7, 11, 2, 30))
527+
528+
assert_datetime(dt, 2134, 7, 11, 2, 30)
529+
assert dt.utcoffset().total_seconds() == 3600
530+
assert dt.dst() == timedelta()
531+
532+
dt = tz.convert(
533+
pendulum.naive(2134, 10, 31, 2, 30),
534+
dst_rule=pendulum.PRE_TRANSITION
535+
)
536+
537+
assert_datetime(dt, 2134, 10, 31, 2, 30)
538+
assert dt.utcoffset().total_seconds() == 3600
539+
assert dt.dst() == timedelta()
540+
541+
dt = tz.convert(
542+
pendulum.naive(2134, 10, 31, 2, 30),
543+
dst_rule=pendulum.POST_TRANSITION
544+
)
545+
546+
assert_datetime(dt, 2134, 10, 31, 2, 30)
547+
assert dt.utcoffset().total_seconds() == 3600
548+
assert dt.dst() == timedelta()
549+
550+
500551
def test_repr():
501552
tz = timezone('Europe/Paris')
502553

0 commit comments

Comments
 (0)