Skip to content

Commit

Permalink
Fix errors where hours and days were not handled correctly when addin…
Browse files Browse the repository at this point in the history
…g durations (#775)

Fixes #768
  • Loading branch information
sdispater authored Dec 15, 2023
1 parent 0a884dd commit 78fdc33
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 5 deletions.
4 changes: 1 addition & 3 deletions src/pendulum/datetime.py
Original file line number Diff line number Diff line change
Expand Up @@ -685,9 +685,7 @@ def _add_timedelta_(self, delta: datetime.timedelta) -> Self:
microseconds=delta.microseconds,
)
elif isinstance(delta, pendulum.Duration):
return self.add(
years=delta.years, months=delta.months, seconds=delta._total
)
return self.add(**delta._signature) # type: ignore[attr-defined]

return self.add(seconds=delta.total_seconds())

Expand Down
16 changes: 15 additions & 1 deletion src/pendulum/duration.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,17 @@ def __new__(
self._months = months
self._years = years

self._signature = { # type: ignore[attr-defined]
"years": years,
"months": months,
"weeks": weeks,
"days": days,
"hours": hours,
"minutes": minutes,
"seconds": seconds,
"microseconds": microseconds + milliseconds * 1000,
}

return self

def total_minutes(self) -> float:
Expand Down Expand Up @@ -440,7 +451,10 @@ def __mod__(self, other: timedelta) -> Self:

def __divmod__(self, other: timedelta) -> tuple[int, Duration]:
if isinstance(other, timedelta):
q, r = divmod(self._to_microseconds(), other._to_microseconds()) # type: ignore[attr-defined] # noqa: E501
q, r = divmod(
self._to_microseconds(),
other._to_microseconds(), # type: ignore[attr-defined]
)

return q, self.__class__(0, 0, r)

Expand Down
14 changes: 13 additions & 1 deletion tests/datetime/test_add.py
Original file line number Diff line number Diff line change
Expand Up @@ -252,13 +252,25 @@ def test_add_time_to_new_transition_repeated_big():
assert not dt.is_dst()


def test_add_interval():
def test_add_duration_across_transition():
dt = pendulum.datetime(2017, 3, 11, 10, 45, tz="America/Los_Angeles")
new = dt + pendulum.duration(hours=24)

assert_datetime(new, 2017, 3, 12, 11, 45)


def test_add_duration_across_transition_days():
dt = pendulum.datetime(2017, 3, 11, 10, 45, tz="America/Los_Angeles")
new = dt + pendulum.duration(days=1)

assert_datetime(new, 2017, 3, 12, 10, 45)

dt = pendulum.datetime(2023, 11, 5, 0, 0, tz="America/Chicago")
new = dt + pendulum.duration(days=1)

assert_datetime(new, 2023, 11, 6, 0, 0)


def test_interval_over_midnight_tz():
start = pendulum.datetime(2018, 2, 25, tz="Europe/Paris")
end = start.add(hours=1)
Expand Down

0 comments on commit 78fdc33

Please sign in to comment.