Skip to content

Commit a39d8ec

Browse files
pR0Pssdispater
authored andcommitted
Fix instance() behaviour with pytz offsets (#158)
`pytz` has a class of timezone called a `FixedOffset`. This class only stores an offset, not a zone name. When calling `instance()` on a datetime that was using one of these `FixedOffset` objects as a timezone, Pendulum would totally ignore the offset and use the local timezone instead. This would happen even if a `tz` argument was directly supplied to the `instance()` call. Additionally, the fallback to a fixed offset would always use the datetime's timezone, even it if was `None` and a `tz` argument was supplied to the `instance()` call. This commit makes 2 small changes: - The `zone` property of the "effective timezone" (the datetime's `tzinfo` with a fallback to the passed in `tz`) is only used if it is non-null. This fixes using `FixedOffset` objects as timezones. - The fallback to a fixed offset now uses the offset of the "effective timezone" instead of the datetime's offset. This correctly handles cases where the timezone on the datetime is `None` and a fallback is provided.
1 parent c30ac41 commit a39d8ec

File tree

2 files changed

+21
-2
lines changed

2 files changed

+21
-2
lines changed

pendulum/pendulum.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -205,13 +205,13 @@ def instance(cls, dt, tz=UTC):
205205
# Checking for pytz/tzinfo
206206
if isinstance(tz, datetime.tzinfo) and not isinstance(tz, (Timezone, TimezoneInfo)):
207207
# pytz
208-
if hasattr(tz, 'localize'):
208+
if hasattr(tz, 'localize') and tz.zone:
209209
tz = tz.zone
210210
else:
211211
# We have no sure way to figure out
212212
# the timezone name, we fallback
213213
# on a fixed offset
214-
tz = dt.utcoffset().total_seconds() / 3600
214+
tz = tz.utcoffset(dt).total_seconds() / 3600
215215

216216
return cls(
217217
dt.year, dt.month, dt.day,

tests/pendulum_tests/test_construct.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -135,6 +135,25 @@ def test_instance_timezone_aware_datetime_pytz(self):
135135
)
136136
self.assertEqual('Europe/Paris', now.timezone_name)
137137

138+
def test_instance_timezone_aware_datetime_pytz_offset(self):
139+
# Impossible timezone of +21 (won't accidentally match the local offset)
140+
fixed_offset = pytz.FixedOffset(21 * 60)
141+
142+
now = Pendulum.instance(
143+
datetime.now(fixed_offset)
144+
)
145+
self.assertEqual(21, now.offset_hours)
146+
147+
now = Pendulum.instance(
148+
datetime.now(), fixed_offset
149+
)
150+
self.assertEqual(21, now.offset_hours)
151+
152+
now = Pendulum.instance(
153+
datetime.now(fixed_offset), pytz.timezone('Europe/Paris')
154+
)
155+
self.assertEqual(21, now.offset_hours)
156+
138157
def test_instance_timezone_aware_datetime_any_tzinfo(self):
139158
dt = datetime(2016, 8, 7, 12, 34, 56, tzinfo=tz.gettz('Europe/Paris'))
140159
now = Pendulum.instance(dt)

0 commit comments

Comments
 (0)