Skip to content

Fix ordinal() wrong suffix for negative integers - #486

Closed
ApparentlyTejas wants to merge 1 commit into
python-humanize:mainfrom
ApparentlyTejas:fix/ordinal-wrong-suffix-for-negative-integers
Closed

ApparentlyTejas wants to merge 1 commit into
python-humanize:mainfrom
ApparentlyTejas:fix/ordinal-wrong-suffix-for-negative-integers

Conversation

@ApparentlyTejas

Copy link
Copy Markdown

ordinal() gives the wrong suffix for every negative integer:

>>> humanize.ordinal(-1)
'-1th'   # should be '-1st'
>>> humanize.ordinal(-2)
'-2th'   # should be '-2nd'
>>> humanize.ordinal(-21)
'-21th'  # should be '-21st'

The docstring says ordinal() "Works for any integer", with no carve-out for negatives.

Root cause: in ordinal(), the digit used for the suffix lookup is computed as value % 10 (and the teen-check as value % 100 in (11, 12, 13)). Python's % with a positive divisor always returns a non-negative result, so for negative value this doesn't give the "last digit" you'd expect: -1 % 10 == 9, -2 % 10 == 8, -21 % 10 == 9, and -1 % 100 == 99 (never matches the teen exception). Every one of those lands on a suffix-table index that resolves to "th".

Fix: compute the digit from abs(value), but keep formatting the original signed value in the output string.

Added test cases for -1, -2, -3, -4 (base suffixes), -11, -12, -13 (teen exception), -21 (back to "st" after the teens), and -100/-111 for good measure. Ran the full suite locally, 756 passed / 132 skipped, no failures.

value % 10 and value % 100 return non-negative results for negative
value in Python, so the suffix lookup in ordinal() always landed on
'th' for negative numbers (e.g. ordinal(-1) gave '-1th', ordinal(-21)
gave '-21th'). Compute the digit off abs(value) instead, while still
formatting the original signed value.
@hugovk

hugovk commented Oct 25, 2026

Copy link
Copy Markdown
Member

Duplicate of #321 and #405. Check next time.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants