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
8 changes: 2 additions & 6 deletions src/humanize/filesize.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,12 +81,8 @@ def naturalsize(
Returns:
str: Human readable representation of a filesize.
"""
if gnu:
suffix = suffixes["gnu"]
elif binary:
suffix = suffixes["binary"]
else:
suffix = suffixes["decimal"]
suffix_key = "gnu" if gnu else "binary" if binary else "decimal"
suffix = suffixes[suffix_key]

base = 1024 if (gnu or binary) else 1000
bytes_ = float(value)
Expand Down
7 changes: 3 additions & 4 deletions src/humanize/lists.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def natural_list(items: list[Any]) -> str:
return ""
if len(items) == 1:
return str(items[0])
elif len(items) == 2:
return f"{str(items[0])} and {str(items[1])}"
else:
return ", ".join([str(item) for item in items[:-1]]) + f" and {str(items[-1])}"
if len(items) == 2:
return f"{items[0]!s} and {items[1]!s}"
return ", ".join([str(item) for item in items[:-1]]) + f" and {items[-1]!s}"
6 changes: 3 additions & 3 deletions src/humanize/number.py
Original file line number Diff line number Diff line change
Expand Up @@ -540,19 +540,19 @@ def metric(value: float, unit: str = "", precision: int = 3) -> str:

if not math.isfinite(value):
return _format_not_finite(value)
exponent = int(math.floor(math.log10(abs(value)))) if value != 0 else 0
exponent = math.floor(math.log10(abs(value))) if value != 0 else 0

if exponent >= 33 or exponent < -30:
return scientific(value, precision - 1) + unit

old_bucket = exponent // 3 * 3
value /= 10**old_bucket
digits = int(max(0, precision - exponent % 3 - 1))
digits = max(0, precision - exponent % 3 - 1)
if exponent < 30 and round(abs(value), digits) >= 1000:
exponent += 3 - exponent % 3
new_bucket = exponent // 3 * 3
value /= 10 ** (new_bucket - old_bucket)
digits = int(max(0, precision - exponent % 3 - 1))
digits = max(0, precision - exponent % 3 - 1)

if exponent >= 3:
ordinal_ = "kMGTPEZYRQ"[exponent // 3 - 1]
Expand Down
23 changes: 13 additions & 10 deletions src/humanize/time.py
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ def naturaldelta(

return _ngettext("%d minute", "%d minutes", minutes) % minutes

if 3600 <= delta.seconds:
if delta.seconds >= 3600:
hours = round(delta.seconds / 3600)
if hours == 1:
return _("an hour")
Expand Down Expand Up @@ -313,6 +313,15 @@ def _convert_aware_datetime(
return value


def _today_for_value(value: dt.date | dt.datetime) -> dt.date:
"""Return today's date in the timezone of a tz-aware datetime value."""
import datetime as dt

if isinstance(value, dt.datetime) and value.tzinfo is not None:
return dt.datetime.now(value.tzinfo).date()
return dt.date.today()


def naturalday(value: dt.date | dt.datetime, format: str = "%b %d") -> str:
"""Return a natural day.

Expand All @@ -326,10 +335,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:
today = dt.datetime.now(value.tzinfo).date()
else:
today = dt.date.today()
today = _today_for_value(value)
value = dt.date(value.year, value.month, value.day)
except AttributeError:
# Passed value wasn't date-ish
Expand Down Expand Up @@ -357,10 +363,7 @@ def naturaldate(value: dt.date | dt.datetime) -> str:

original_value = value
try:
if isinstance(value, dt.datetime) and value.tzinfo is not None:
today = dt.datetime.now(value.tzinfo).date()
else:
today = dt.date.today()
today = _today_for_value(value)
value = dt.date(value.year, value.month, value.day)
except AttributeError:
# Passed value wasn't date-ish
Expand Down Expand Up @@ -643,7 +646,7 @@ def precisedelta(
import math

texts: list[str] = []
for unit, fmt in zip(reversed(Unit), fmts):
for unit, fmt in zip(reversed(Unit), fmts, strict=True):
singular_txt, plural_txt, fmt_value = fmt
if fmt_value > 0 or (not texts and unit == min_unit):
_fmt_value = 2 if 1 < fmt_value < 2 else int(fmt_value)
Expand Down
6 changes: 3 additions & 3 deletions tests/test_time.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

with freeze_time(FROZEN_DATE):
NOW = dt.datetime.now()
NOW_UTC = dt.datetime.now(tz=dt.timezone.utc)
NOW_UTC = dt.datetime.now(tz=dt.UTC)
NOW_UTC_PLUS_01_00 = dt.datetime.now(tz=dt.timezone(offset=dt.timedelta(hours=1)))
TODAY = dt.date.today()
TOMORROW = TODAY + ONE_DAY_DELTA
Expand Down Expand Up @@ -66,7 +66,7 @@ def test_date_and_delta() -> None:
td_tests = [td(seconds=x) for x in int_tests]
results = [(now - td(seconds=x), td(seconds=x)) for x in int_tests]
for t in (int_tests, date_tests, td_tests):
for arg, result in zip(t, results):
for arg, result in zip(t, results, strict=True):
date, d = time._date_and_delta(arg)
assert_equal_datetime(date, result[0])
assert_equal_timedelta(d, result[1])
Expand Down Expand Up @@ -303,7 +303,7 @@ def test_naturaldate(test_input: dt.date, expected: str) -> None:
@freeze_time("2023-10-15 23:00:00+00:00")
def test_naturaldate_tz_aware() -> None:
"""naturaldate should compare dates in the timezone of the given value."""
utc = dt.timezone.utc
utc = dt.UTC
aedt = dt.timezone(dt.timedelta(hours=11))
cest = dt.timezone(dt.timedelta(hours=2))
edt = dt.timezone(dt.timedelta(hours=-4))
Expand Down