Skip to content

Commit

Permalink
Move logic to convert aware datetime to naive into function (#123)
Browse files Browse the repository at this point in the history
Co-authored-by: Hugo van Kemenade <hugovk@users.noreply.github.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
  • Loading branch information
hugovk and pre-commit-ci[bot] committed Aug 16, 2023
2 parents 6d474ed + 5262409 commit 7abebba
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 3 deletions.
16 changes: 13 additions & 3 deletions src/humanize/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
import typing
from enum import Enum
from functools import total_ordering
from typing import Any

from .i18n import _gettext as _
from .i18n import _ngettext
Expand Down Expand Up @@ -245,10 +246,10 @@ def naturaltime(
Returns:
str: A natural representation of the input in a resolution that makes sense.
"""
now = when or _now()
value = _convert_aware_datetime(value)
when = _convert_aware_datetime(when)

if isinstance(value, dt.datetime) and value.tzinfo is not None:
value = dt.datetime.fromtimestamp(value.timestamp())
now = when or _now()

date, delta = _date_and_delta(value, now=now)
if date is None:
Expand All @@ -266,6 +267,15 @@ def naturaltime(
return str(ago % delta)


def _convert_aware_datetime(
value: dt.datetime | dt.timedelta | float | None,
) -> Any:
"""Convert aware datetime to naive datetime and pass through any other type."""
if isinstance(value, dt.datetime) and value.tzinfo is not None:
value = dt.datetime.fromtimestamp(value.timestamp())
return value


def naturalday(value: dt.date | dt.datetime, format: str = "%b %d") -> str:
"""Return a natural day.
Expand Down
34 changes: 34 additions & 0 deletions tests/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,40 @@ def test_naturaltime_timezone(test_input: dt.datetime, expected: str) -> None:
assert humanize.naturaltime(test_input) == expected


@freeze_time("2020-02-02")
@pytest.mark.parametrize(
"test_input, expected",
[
(NOW_UTC, "now"),
(NOW_UTC - dt.timedelta(seconds=1), "a second ago"),
(NOW_UTC - dt.timedelta(seconds=30), "30 seconds ago"),
(NOW_UTC - dt.timedelta(minutes=1, seconds=30), "a minute ago"),
(NOW_UTC - dt.timedelta(minutes=2), "2 minutes ago"),
(NOW_UTC - dt.timedelta(hours=1, minutes=30, seconds=30), "an hour ago"),
(NOW_UTC - dt.timedelta(hours=23, minutes=50, seconds=50), "23 hours ago"),
(NOW_UTC - dt.timedelta(days=1), "a day ago"),
(NOW_UTC - dt.timedelta(days=500), "1 year, 4 months ago"),
(NOW_UTC - dt.timedelta(days=365 * 2 + 35), "2 years ago"),
(NOW_UTC + dt.timedelta(seconds=1), "a second from now"),
(NOW_UTC + dt.timedelta(seconds=30), "30 seconds from now"),
(NOW_UTC + dt.timedelta(minutes=1, seconds=30), "a minute from now"),
(NOW_UTC + dt.timedelta(minutes=2), "2 minutes from now"),
(NOW_UTC + dt.timedelta(hours=1, minutes=30, seconds=30), "an hour from now"),
(NOW_UTC + dt.timedelta(hours=23, minutes=50, seconds=50), "23 hours from now"),
(NOW_UTC + dt.timedelta(days=1), "a day from now"),
(NOW_UTC + dt.timedelta(days=500), "1 year, 4 months from now"),
(NOW_UTC + dt.timedelta(days=365 * 2 + 35), "2 years from now"),
# regression tests for bugs in post-release humanize
(NOW_UTC + dt.timedelta(days=10000), "27 years from now"),
(NOW_UTC - dt.timedelta(days=365 + 35), "1 year, 1 month ago"),
(NOW_UTC - dt.timedelta(days=365 * 2 + 65), "2 years ago"),
(NOW_UTC - dt.timedelta(days=365 + 4), "1 year, 4 days ago"),
],
)
def test_naturaltime_timezone_when(test_input: dt.datetime, expected: str) -> None:
assert humanize.naturaltime(test_input, when=NOW_UTC) == expected


@pytest.mark.parametrize(
"val, min_unit, expected",
[
Expand Down

0 comments on commit 7abebba

Please sign in to comment.