在PHP中显示带序数后缀的数字

时间:2010-06-24 12:40:31

标签: php numbers

我想按以下方式显示数字

  • 1作为第1,
  • 2为第2,
  • ...,
  • 150为150th。

如何为代码中的每个数字找到正确的序数后缀(st,nd,rd或th)?

15 个答案:

答案 0 :(得分:258)

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];

$number是您要编写的号码。适用于任何自然数。

作为一项功能:

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);

答案 1 :(得分:119)

PHP has built-in functionality for this。它甚至处理国际化!

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

请注意,此功能仅适用于PHP 5.3.0及更高版本。

答案 2 :(得分:18)

这可以通过利用PHP内置日期/时间函数中的类似功能在一行中完成。我谦卑地提交:

<强>解决方案:

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

详细说明:

内置date()函数具有后缀逻辑,用于处理第n天的计算。当格式字符串中给出S时返回后缀:

date( 'S' , ? );

由于date()需要时间戳(上面为?),我们会将整数$n作为day参数传递给mktime()并使用虚拟1hourminutesecond的{​​{1}}值:

month

这实际上在一个月中的某一天(即date( 'S' , mktime( 1 , 1 , 1 , 1 , $n ) ); )上的值超出范围时优雅地失败了,但我们可以在29处添加一些简单的内联逻辑来限制$n > 31

$n

这个失败的唯一正值 2017年5月)是date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20))*10 + $n%10) )); ,但在特殊情况下通过添加10可以很容易地解决这个问题:

$n == 0

2017年5月更新

正如@donatJ所观察到的,上述失败超过100(例如“111st”),因为date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) )); 检查总是返回true。为了在每个世纪重置这些,我们在比较中添加一个过滤器:

>=20

为方便起见,请将其包装在一个功能中,然后离开!

答案 3 :(得分:14)

这是一个单行:

$a = <yournumber>;
echo $a.substr(date('jS', mktime(0,0,0,1,($a%10==0?9:($a%100>20?$a%10:$a%100)),2000)),-2);

可能是最短的解决方案。当然可以用函数包装:

function ordinal($a) {
  // return English ordinal number
  return $a.substr(date('jS', mktime(0,0,0,1,($a%10==0?9:($a%100>20?$a%10:$a%100)),2000)),-2);
}

此致 保罗

EDIT1:修正11到13的代码。

EDIT2:修正111,211,...

的代码

EDIT3:现在它也适用于10的倍数。

答案 4 :(得分:13)

来自http://www.phpro.org/examples/Ordinal-Suffix.html

<?php

/**
 *
 * @return number with ordinal suffix
 *
 * @param int $number
 *
 * @param int $ss Turn super script on/off
 *
 * @return string
 *
 */
function ordinalSuffix($number, $ss=0)
{

    /*** check for 11, 12, 13 ***/
    if ($number % 100 > 10 && $number %100 < 14)
    {
        $os = 'th';
    }
    /*** check if number is zero ***/
    elseif($number == 0)
    {
        $os = '';
    }
    else
    {
        /*** get the last digit ***/
        $last = substr($number, -1, 1);

        switch($last)
        {
            case "1":
            $os = 'st';
            break;

            case "2":
            $os = 'nd';
            break;

            case "3":
            $os = 'rd';
            break;

            default:
            $os = 'th';
        }
    }

    /*** add super script ***/
    $os = $ss==0 ? $os : '<sup>'.$os.'</sup>';

    /*** return ***/
    return $number.$os;
}
?> 

答案 5 :(得分:7)

我为PHP4写了这个。 它一直工作正常&amp;这很经济。

function getOrdinalSuffix($number) {
    $number = abs($number) % 100;
    $lastChar = substr($number, -1, 1);
    switch ($lastChar) {
        case '1' : return ($number == '11') ? 'th' : 'st';
        case '2' : return ($number == '12') ? 'th' : 'nd';
        case '3' : return ($number == '13') ? 'th' : 'rd'; 
    }
    return 'th';  
}

答案 6 :(得分:7)

简单易行的答案将是:

$Day = 3; 
echo date("S", mktime(0, 0, 0, 0, $Day, 0));

//OUTPUT - rd

答案 7 :(得分:3)

通常,您可以使用它并调用 echo get_placing_string(100);

<?php
function get_placing_string($placing){
    $i=intval($placing%10);
    $place=substr($placing,-2); //For 11,12,13 places

    if($i==1 && $place!='11'){
        return $placing.'st';
    }
    else if($i==2 && $place!='12'){
        return $placing.'nd';
    }

    else if($i==3 && $place!='13'){
        return $placing.'rd';
    }
    return $placing.'th';
}
?>

答案 8 :(得分:3)

你只需要申请给定的功能。

function addOrdinalNumberSuffix($num) {
  if (!in_array(($num % 100),array(11,12,13))){
    switch ($num % 10) {
      // Handle 1st, 2nd, 3rd
      case 1:  return $num.'st';
      case 2:  return $num.'nd';
      case 3:  return $num.'rd';
    }
  }
  return $num.'th';
}

答案 9 :(得分:2)

我创建的函数不依赖于PHP的date();函数,因为它不是必需的,但也使它像我认为的那样紧凑和简短。< / p>

代码 :(总共121个字节)

function ordinal($i) { // PHP 5.2 and later
  return($i.(($j=abs($i)%100)>10&&$j<14?'th':(($j%=10)>0&&$j<4?['st', 'nd', 'rd'][$j-1]:'th')));
}

下面更紧凑的代码。

它的工作原理如下

printf("The %s hour.\n",    ordinal(0));   // The 0th hour.
printf("The %s ossicle.\n", ordinal(1));   // The 1st ossicle.
printf("The %s cat.\n",     ordinal(12));  // The 12th cat.
printf("The %s item.\n",    ordinal(-23)); // The -23rd item.

了解此功能的事项

  • 它处理与正整数相同的负整数并保持符号。
  • 按预期返回 -teen 数字的第11,12,13,811,812,813等。
  • 它不会检查小数,但会将它们留在原位(在最终返回语句的开头使用floor($i)round($i)ceil($i)
  • 您还可以在最终return语句的开头添加format_number($i)以获取以逗号分隔的整数(如果您显示数千,数百万等)。
  • 如果您只想在没有输入内容的情况下返回序数后缀,则可以从return语句的开头删除$i

这个函数的工作原理是从2006年11月发布的PHP 5.2开始,纯粹是因为短数组语法。如果您之前有版本,请升级,因为您已经过时了近十年!如果做不到这一点,只需将内嵌['st', 'nd', 'rd']替换为包含array('st', 'nd', 'rd');的临时变量。

相同的功能(不返回输入),但我的简短功能的分解视图,以便更好地理解:

function ordinal($i) {
  $j = abs($i); // make negatives into positives
  $j = $j%100; // modulo 100; deal only with ones and tens; 0 through 99

  if($j>10 && $j<14) // if $j is over 10, but below 14 (so we deal with 11 to 13)
    return('th'); // always return 'th' for 11th, 13th, 62912th, etc.

  $j = $j%10; // modulo 10; deal only with ones; 0 through 9

  if($j==1) // 1st, 21st, 31st, 971st
    return('st');

  if($j==2) // 2nd, 22nd, 32nd, 582nd
    return('nd'); // 

  if($j==3) // 3rd, 23rd, 33rd, 253rd
    return('rd');

  return('th'); // everything else will suffixed with 'th' including 0th
}

代码更新

这里是一个修改后的版本,它缩短了14个字节(总共107个字节):

function ordinal($i) {
  return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');
}

或者尽可能短,缩短25个字节(总共96个字节):

function o($i){return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');}

使用这最后一项功能,只需致电o(121);,它就会与我列出的其他功能完全相同。

代码更新#2

Ben我一起工作并将其减少了38个字节(总共83个字节):

function o($i){return$i.@(($j=abs($i)%100)>10&&$j<14?th:[th,st,nd,rd][$j%10]?:th);}

我们认为它不可能比这更短!但是,愿意被证明是错误的。 :)

希望大家都喜欢。

答案 10 :(得分:1)

本月日期(最多31个)的更短版本,而不是使用mktime()而不需要pecl intl:

function ordinal($n) {
    return (new DateTime('Jan '.$n))->format('jS');
}

或程序上:

echo date_format(date_create('Jan '.$n), 'jS');

这当然有效,因为我选择的默认月份(1月)有31天。

有趣的是,如果你在二月(或另一个月没有31天)尝试它,它会在结束前重新开始:

...clip...
31st
1st
2nd
3rd

因此,您可以在循环中使用日期说明符t来计算本月的日期:该月的天数。

答案 11 :(得分:1)

function ordinal($number){

    $last=substr($number,-1);
    if( $last>3 || $last==0 || ( $number >= 11 && $number <= 19 ) ){
      $ext='th';
    }else if( $last==3 ){
      $ext='rd';
    }else if( $last==2 ){
      $ext='nd';
    }else{
      $ext='st';
    }
    return $number.$ext;
  }

答案 12 :(得分:0)

PHP.net

中找到答案
<?php
function ordinal($num)
{
    // Special case "teenth"
    if ( ($num / 10) % 10 != 1 )
    {
        // Handle 1st, 2nd, 3rd
        switch( $num % 10 )
        {
            case 1: return $num . 'st';
            case 2: return $num . 'nd';
            case 3: return $num . 'rd';  
        }
    }
    // Everything else is "nth"
    return $num . 'th';
}
?>

答案 13 :(得分:0)

这是使用日期函数的另一个非常简短的版本。它适用于任何数字(不受月份的天数限制),并考虑到* 11 * 12 * 13th不遵循* 1 * 2nd * 3rd格式。

function getOrdinal($n)
{
    return $n . date_format(date_create('Jan ' . ($n % 100 < 20 ? $n % 20 : $n % 10)), 'S');
}

答案 14 :(得分:-1)

我找到了这个小片段

<?php

  function addOrdinalNumberSuffix($num) {
    if (!in_array(($num % 100),array(11,12,13))){
      switch ($num % 10) {
        // Handle 1st, 2nd, 3rd
        case 1:  return $num.'st';
        case 2:  return $num.'nd';
        case 3:  return $num.'rd';
      }
    }
    return $num.'th';
  }

?>

HERE