arrow-py / arrow

🏹 Better dates & times for Python
https://arrow.readthedocs.io
Apache License 2.0
8.71k stars 673 forks source link

Humanize Bug when using multiple Granularities #948

Open anishnya opened 3 years ago

anishnya commented 3 years ago

Issue Description

Humanize appears to have a bug when dealing with multiple granularities.

arw = arrow.Arrow(2017, 1, 1, 0, 0, 0)
time_future = arw.shift(years=1, months=4, days=2, hours=6, seconds=2)
time_future_string = time_future.humanize(arw, locale="en", granularity=["year", "month", "day", "hour", "second"])
print("Starting time")
print(arw)
print("Actual new time after shift")
print(time_future)
print("Humanize shift")
print(time_future_string)

The shift function returns the expected time of May 3rd 2018, however running humanize on this object says "in a year 4 months 0 days 6 hours and 2 seconds." We would expect to see "in a year 4 months 2 days 6 hours and 2 seconds." Initially, I ran into this issue while attempting to shift across time spans of 10 years, so I thought the two-day discrepancy may be related to how leap years/leap days were handled. However, it appears to be a more generalized issue since there is no leap day between 2017 and 2018 May 3rd.

System Info

systemcatch commented 3 years ago

Right so I've been able to reproduce this locally and I think the bug is happening due to an issue with arrow's month humanize limits (see #749).

In brief the humanize method currently works on the assumption that every month has 30.5 days. Over the course of a year (non leap) this results in being one day short.

This causes problems in several areas and we are looking at ways to fix this.