Display numbers with ordinal suffix

04/06/2020 17:30:01

I want to display numbers as follows

  • 1 as 1st,
  • 2 as 2nd,
  • ...,
  • 150 as 150th.

How should I find the correct ordinal suffix (st, nd, rd or th) for each number in my code?

Verified Answer (276 Votes)

06/24/2010 17:49:04

from wikipedia:

$ends = array('th','st','nd','rd','th','th','th','th','th','th');
if (($number %100) >= 11 && ($number%100) <= 13)
   $abbreviation = $number. 'th';
else
   $abbreviation = $number. $ends[$number % 10];

Where $number is the number you want to write. Works with any natural number.

As a function:

function ordinal($number) {
    $ends = array('th','st','nd','rd','th','th','th','th','th','th');
    if ((($number % 100) >= 11) && (($number%100) <= 13))
        return $number. 'th';
    else
        return $number. $ends[$number % 10];
}
//Example Usage
echo ordinal(100);
276

Answer #2 (137 Votes)

12/09/2010 02:43:26

PHP has built-in functionality for this. It even handles internationalization!

$locale = 'en_US';
$nf = new NumberFormatter($locale, NumberFormatter::ORDINAL);
echo $nf->format($number);

Note that this functionality is only available in PHP 5.3.0 and later.

137

Answer #3 (20 Votes)

12/01/2011 23:11:57

This can be accomplished in a single line by leveraging similar functionality in PHP's built-in date/time functions. I humbly submit:

Solution:

function ordinalSuffix( $n )
{
  return date('S',mktime(1,1,1,1,( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));
}

Detailed Explanation:

The built-in date() function has suffix logic for handling nth-day-of-the-month calculations. The suffix is returned when S is given in the format string:

date( 'S' , ? );

Since date() requires a timestamp (for ? above), we'll pass our integer $n as the day parameter to mktime() and use dummy values of 1 for the hour, minute, second, and month:

date( 'S' , mktime( 1 , 1 , 1 , 1 , $n ) );

This actually fails gracefully on values out of range for a day of the month (i.e. $n > 31) but we can add some simple inline logic to cap $n at 29:

date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20))*10 + $n%10) ));

The only positive value(May 2017) this fails on is $n == 0, but that's easily fixed by adding 10 in that special case:

date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));

Update, May 2017

As observed by @donatJ, the above fails above 100 (e.g. "111st"), since the >=20 checks are always returning true. To reset these every century, we add a filter to the comparison:

date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n%100>=20)+($n==0))*10 + $n%10) ));

Just wrap it in a function for convenience and off you go!

20
3
Hack Hex uses Stack Exchance API by the Stack Exchange Inc. to scrape questions/answers under Creative Commons license.