Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/humanize/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ def _convert_aware_datetime(

import datetime as dt

if isinstance(value, dt.datetime) and value.tzinfo is not None:
if isinstance(value, dt.datetime) and value.utcoffset() is not None:
value = dt.datetime.fromtimestamp(value.timestamp()) # noqa: DTZ006
return value

Expand All @@ -338,7 +338,7 @@ def naturalday(value: dt.date | dt.datetime, format: str = "%b %d") -> str:
try:
# When value is a tz-aware datetime, compute "today" in that timezone
# so the comparison uses the correct local date.
if isinstance(value, dt.datetime) and value.tzinfo is not None:
if isinstance(value, dt.datetime) and value.utcoffset() is not None:
today = dt.datetime.now(value.tzinfo).date()
else:
today = dt.date.today() # noqa: DTZ011
Expand Down Expand Up @@ -369,7 +369,7 @@ def naturaldate(value: dt.date | dt.datetime) -> str:

original_value = value
try:
if isinstance(value, dt.datetime) and value.tzinfo is not None:
if isinstance(value, dt.datetime) and value.utcoffset() is not None:
today = dt.datetime.now(value.tzinfo).date()
else:
today = dt.date.today() # noqa: DTZ011
Expand Down
41 changes: 41 additions & 0 deletions tests/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,17 @@ def __str__(self) -> str:
return f"{self.year}-{self.month}-{self.day}"


class NaiveTimezone(dt.tzinfo):
def utcoffset(self, value: dt.datetime | None) -> None:
return None

def dst(self, value: dt.datetime | None) -> None:
return None

def tzname(self, value: dt.datetime | None) -> None:
return None


VALUE_ERROR_TEST = FakeDate(290149024, 2, 2)
OVERFLOW_ERROR_TEST = FakeDate(120390192341, 2, 2)

Expand Down Expand Up @@ -280,6 +291,36 @@ def test_naturalday(test_args: list[typing.Any], expected: str) -> None:
assert humanize.naturalday(*test_args) == expected


@freeze_time(FROZEN_DATE)
@pytest.mark.parametrize("formatter", ["naturalday", "naturaldate", "naturaltime"])
@pytest.mark.parametrize("tzinfo", [None, NaiveTimezone(), dt.UTC])
def test_datetime_awareness(formatter: str, tzinfo: dt.tzinfo | None) -> None:
value = dt.datetime(2010, 2, 2, tzinfo=tzinfo)
format_time = getattr(humanize, formatter)
expected = "now" if formatter == "naturaltime" else "today"
assert format_time(value) == expected
if value.utcoffset() is None:
assert format_time(value) == format_time(value.replace(tzinfo=None))


@pytest.mark.parametrize(
"value_tzinfo, when_tzinfo",
[
(None, None),
(NaiveTimezone(), None),
(None, NaiveTimezone()),
(NaiveTimezone(), NaiveTimezone()),
(dt.UTC, dt.UTC),
],
)
def test_naturaltime_when_datetime_awareness(
value_tzinfo: dt.tzinfo | None, when_tzinfo: dt.tzinfo | None
) -> None:
value = dt.datetime(2010, 2, 2, 12, tzinfo=value_tzinfo)
when = dt.datetime(2010, 2, 2, 11, tzinfo=when_tzinfo)
assert humanize.naturaltime(value, when=when) == "an hour from now"


@freeze_time(FROZEN_DATE)
@pytest.mark.parametrize(
"test_input, expected",
Expand Down