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

Fixes #768
  • Loading branch information
sdispater committed Dec 15, 2023
1 parent 1ff9a1c commit 12d5f09
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 12d5f09

Please sign in to comment.