humanize
humanize copied to clipboard
naturaldate() gives the wrong answer for tz-aware datetimes
The calculation in naturaldate()
of how many days ahead or behind a date is, is incorrect for tz-aware datetimes.
Consider when the current time is 2023-10-15 23:00:00+00:00 (UTC). In various other timezones this is:
AEDT: 2023-10-16 10:00:00+11:00
CEST: 2023-10-16 01:00:00+02:00
EDT: 2023-10-15 19:00:00-04:00
PDT: 2023-10-15 16:00:00-07:00
Now consider a time 7 hours in the future. Will that be "today" or "tomorrow"? Relative to UTC this should be "tomorrow", but for the other timezones we would expect:
- AEDT: today
- CEST: today
- EDT: tomorrow
- PDT: today
So all the following test cases should pass, but the test cases for AEDT and CEST currently fail:
def test_naturaldate_tz_aware():
utc = dt.timezone.utc
aedt = dt.timezone(dt.timedelta(hours=11))
cest = dt.timezone(dt.timedelta(hours=2))
edt = dt.timezone(dt.timedelta(hours=-4))
pdt = dt.timezone(dt.timedelta(hours=-7))
future = dt.datetime(2023, 10, 16, hour=6, tzinfo=utc)
with freeze_time('2023-10-15 23:00:00+00:00'):
# We want to know whether 7 hours in the future is "today" or
# "tomorrow":
# Now in UTC: 2023-10-15 23:00:00+00:00
# Future in UTC: 2023-10-16 06:00:00+00:00
assert humanize.naturaldate(future) == "tomorrow"
# Now in AEDT: 2023-10-16 10:00:00+11:00
# Future in AEDT: 2023-10-16 17:00:00+11:00
assert humanize.naturaldate(future.astimezone(aedt)) == "today" # FAILS
# Now in CEST: 2023-10-16 01:00:00+02:00
# Future in CEST: 2023-10-16 08:00:00+02:00
assert humanize.naturaldate(future.astimezone(cest)) == "today" # FAILS
# Now in EDT: 2023-10-15 19:00:00-04:00
# Future in EDT: 2023-10-16 02:00:00-04:00
assert humanize.naturaldate(future.astimezone(edt)) == "tomorrow"
# Now in PDT: 2023-10-15 16:00:00-07:00
# Future in PDT: 2023-10-15 23:00:00-07:00
assert humanize.naturaldate(future.astimezone(pdt)) == "today"