Skip to content

Commit e4cbd28

Browse files
pR0Pssdispater
authored andcommitted
Fix RecursionError when adding to a DateTime with a FixedTimezone (#431)
This seems to have been caused by `bpo-32417`. Before that change, adding a timedelta to a date/datetime subclass would always return an instance of date/datetime instead of the subclass. After the change, the subclass is preserved. The RecursionError was caused by adding a timedelta to a DateTime. Doing this uses the `convert` method of the DateTime's timezone to convert the new DateTime into the correct timezone. In the case of FixedTimezones, this requires adding the UTC offset of the timezone (a timedelta) to the DateTime, causing the recursion. Before bpo-32417, the subclass of the DateTime was dropped while calling `astimezone`. This meant that the object that was passed into `fromutc` by `astimezone` was a stdlib datetime, not a Pendulum DateTime. Calling the stdlib datetime's add function would then do the addition and return the result (which would then be upconverted back into a Pendulum DateTime instance). Now, due to the subclass being preserved, the Pendulum DateTime's add function is being called instead, causing the recursion. This commit fixes the RecursionError by always using the stdlib datetime's addition function to add the offset to the DateTime when calling fromutc. bpo-32417: https://bugs.python.org/issue32417 commit: python/cpython@89427cd Fixes #422
1 parent bc32743 commit e4cbd28

2 files changed

Lines changed: 4 additions & 2 deletions

File tree

pendulum/tz/timezone.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -342,7 +342,8 @@ def dst(self, dt): # type: Optional[datetime] # type: (...) -> timedelta
342342
return timedelta()
343343

344344
def fromutc(self, dt): # type: (datetime) -> datetime
345-
return (dt + self._utcoffset).replace(tzinfo=self)
345+
# Use the stdlib datetime's add method to avoid infinite recursion
346+
return (datetime.__add__(dt, self._utcoffset)).replace(tzinfo=self)
346347

347348
def tzname(self, dt): # type: Optional[datetime] # type: (...) -> Union[str, None]
348349
return self._name

tests/datetime/test_add.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -134,8 +134,9 @@ def test_addition_invalid_type():
134134
def test_add_to_fixed_timezones():
135135
dt = pendulum.parse("2015-03-08T01:00:00-06:00")
136136
dt = dt.add(weeks=1)
137+
dt = dt.add(hours=1)
137138

138-
assert_datetime(dt, 2015, 3, 15, 1, 0, 0)
139+
assert_datetime(dt, 2015, 3, 15, 2, 0, 0)
139140
assert dt.timezone_name == "-06:00"
140141
assert dt.offset == -6 * 3600
141142

0 commit comments

Comments
 (0)