diff --git a/src/humanize/number.py b/src/humanize/number.py index 52a5356a..14d09604 100644 --- a/src/humanize/number.py +++ b/src/humanize/number.py @@ -101,6 +101,10 @@ def ordinal(value: NumberOrString, gender: str = "male") -> str: ```pycon >>> ordinal(1) '1st' + >>> ordinal(-1) + '-1st' + >>> ordinal(-11) + '-11th' >>> ordinal(1002) '1002nd' >>> ordinal(103) @@ -136,7 +140,10 @@ def ordinal(value: NumberOrString, gender: str = "male") -> str: except (TypeError, ValueError): return str(value) gender = "male" if gender == "male" else "female" - digit = 0 if value % 100 in (11, 12, 13) else value % 10 + # Suffixes follow the absolute value. Python's % on a negative number + # is not the last digit, so -21 used to render as "-21th". + suffix_value = abs(value) + digit = 0 if suffix_value % 100 in (11, 12, 13) else suffix_value % 10 return f"{value}{P_(*_ORDINAL_SUFFIXES[gender][digit])}" diff --git a/tests/test_number.py b/tests/test_number.py index 5fb12fa6..188c091b 100644 --- a/tests/test_number.py +++ b/tests/test_number.py @@ -25,6 +25,17 @@ ("102", "102nd"), ("103", "103rd"), ("111", "111th"), + (-1, "-1st"), + (-2, "-2nd"), + (-3, "-3rd"), + (-11, "-11th"), + (-12, "-12th"), + (-13, "-13th"), + (-21, "-21st"), + (-22, "-22nd"), + (-23, "-23rd"), + (-101, "-101st"), + (-111, "-111th"), ("something else", "something else"), (None, "None"), (math.nan, "NaN"),