humanize icon indicating copy to clipboard operation
humanize copied to clipboard

naturaldate() gives the wrong answer for tz-aware datetimes

Open edschofield opened this issue 1 year ago • 0 comments

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"

edschofield avatar Oct 16 '23 05:10 edschofield