| FazBrowse GitHub Viewer | Trending | | Home |
| Tools: [Download Repo ZIP] [Original HTTPS Page] |
Duration.__mul__ with a float built the result only from _to_microseconds(), which excludes the years and months components, so Duration(years=1) * 2.0 returned an empty Duration even though Duration(years=1) * 2 (int) and Duration(years=1) / 2.0 (float) both keep them. Scale years and months by the float ratio as well, mirroring the existing __truediv__ implementation.
| Back | FazBrowse Home | New Git URL |
The bug
Multiplying a Duration by a float silently drops the years and months components, even though multiplying by an int — and dividing by a float — both keep them:
Duration(years=2, months=4) * 2.0 returns an empty Duration(). Since * 2 and * 2.0 are mathematically the same operation, this is a clear inconsistency.
Root cause
Duration.__mul__ (src/pendulum/duration.py) builds the float result solely from _to_microseconds(), which by design excludes years/months, and hardcodes them to 0:
__truediv__ and __floordiv__ already handle this correctly by scaling years/months alongside the microseconds.
Fix
Scale years and months by the float ratio too, mirroring the existing __truediv__ float branch:
Now duration(years=1) * 2.0 == duration(years=1) * 2, and a non-integer factor rounds years/months the same way float division already does.
Tests
Added test_multiply_float (mirrors the existing test_divide float case): a float factor matches the integer result, is commutative (2.0 * it), a whole-valued float equals the int product exactly, and a non-integer factor rounds years/months. The new test fails on master (years 0 != 4) and passes with the fix; the full tests/duration suite stays green. ruff and mypy clean.