arrow-py / arrow

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

Arrow.humanize() thinks past date is in the future #1148

Closed hermanoelmhagen closed 1 year ago

hermanoelmhagen commented 1 year ago

Issue Description

Arrow returns "in xx minutes" for time in the past:

>>> arrow.get("16/01/2023, 07:59:48", "DD/MM/YYYY, HH:mm:ss").humanize()
'in 27 minutes'
>>> now = arrow.now()
>>> now
<Arrow [2023-01-16T08:32:25.112674+01:00]>

This might be related to humanize() not taking local timezone into account. Possible workaround is to shift(hours=timezone_diff) before humanizing: arrow.get("16/01/2023, 07:59:48","DD/MM/YYYY, HH:mm:ss".shift(hours=-1).humanize()

System Info

krisfremen commented 1 year ago

.get defaults to using UTC unless a time zone is specified, while .now does use the local time zone and .utcnow uses UTC.

Working as intended.

hermanoelmhagen commented 1 year ago

@krisfremen In this case it seems like neither .get, .now, or .utcnow is the culprit. The issue is more that humanize doesn't understand what time to compare to. In the example I posted I only used .now() to show what my local time actually is, but .humanize thinks that a time that's already passed is in the future since it doesn't take timezone into consideration. Am I misunderstanding something about how to use .get in this scenario?

krisfremen commented 1 year ago

.get defaults to using UTC unless a time zone is specified, while .now does use the local time zone and .utcnow uses UTC.

Few examples to illustrate the above:

arrow.get(arrow.now().format("DD/MM/YYYY, HH:mm:ss"), "DD/MM/YYYY, HH:mm:ss").humanize()

for me this yields the following, but it should be the timezone difference you are in, which in europe you'll be technically "in the future" compared to UTC

4 hours ago

UTC time on the other hand

arrow.get(arrow.utcnow().format( "DD/MM/YYYY, HH:mm:ss"), "DD/MM/YYYY, HH:mm:ss").humanize()

yields

just now


Adding tzinfo when using arrow.now you can specify the timezone you want to use.

arrow.get(arrow.now().format("DD/MM/YYYY, HH:mm:ss"), "DD/MM/YYYY, HH:mm:ss", tzinfo="America/Montreal").humanize()

changing the tzinfo to the timezone you're in should yield:

just now