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

我想要显示数字如下

  • 1作为第一,
  • 2作为第二,
  • 150为150。

我应该如何为我的代码中的每个数字find正确的序号后缀(st,nd,rd或th)?

来自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:

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

PHP有内置的function 。 它甚至处理国际化!

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

请注意,此function仅在PHP 5.3.0及更高版本中可用。

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; } ?> 

这是一个单行的:

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

可能是最短的解决scheme。 当然可以用一个函数来包装:

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

问候,保罗

编辑1:更正从11到13的代码。

EDIT2:纠正111,211,…的代码

编辑3:现在它也正确工作的倍数为10。

这可以通过利用PHP内置date/时间函数中的类似function在一行中完成。 我虚心提交:

解:

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

详细说明:

内置的date()函数具有用于处理第n个月的计算的后缀逻辑。 在格式string中给出S时返回后缀:

 date( 'S' , ? ); 

由于date()需要一个timestamp(用于上面的? ),所以我们将把整数$n作为dayparameter passing给mktime()并在hourminutesecondmonth使用1虚拟值:

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

实际上,这个值实际上在一个月的某一天的值超出范围(即$n > 31 )上优雅地失败了,但是我们可以添加一些简单的内联逻辑来在29:

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

唯一的正面价值 2017年5月 )这个失败是$n == 0 ,但是通过在这种特殊情况下添加10可以很容易地解决这个问题:

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

更新,2017年5月

正如@donatJ所观察到的,上面的失败超过了100(例如“111st”),因为>=20检查总是返回true。 为了重置这些每个世纪,我们添加一个filter来比较:

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

只是将其包装在一个function为方便,离开你去!

我为PHP4写了这个。 它一直工作好,这是非常经济的。

 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'; } 

一般来说,你可以使用它并调用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'; } ?> 

简单和简单的答案将是:

 $Day = 3; echo date("S", mktime(0, 0, 0, 0, $Day, 0)); //OUTPUT - rd 

你只需要应用给定的function。

 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'; } 

我做了一个函数,不依赖PHP的date(); 因为它不是必要的function,但也使它尽可能紧凑和尽可能短,因为我认为目前是可能的。

代码 :(共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. 

知道这个function的东西

  • 它处理与正整数相同的负整数并保持符号。
  • 如预期那样返回十一号,十二号,十三号,八号,八号,八号,八号, 十三号等。
  • 它不会检查小数点,但是会在最终返回语句开始时使用floor($i)round($i)或者ceil($i) )。
  • 你也可以在最后一个return语句的开头添加format_number($i)来得到一个逗号分隔的整数(如果你正在显示数千,数百万等)。
  • 如果您只想返回没有input的序号后缀,就可以从返回语句的开头删除$i

这个函数从2006年11月发布的PHP 5.2开始,纯粹是因为数组语法短。 如果你之前有一个版本,那么请升级,因为你已经过了将近十年了! 否则,只需用一个包含array('st', 'nd', 'rd');的临时variablesreplacein-line ['st', 'nd', 'rd'] array('st', 'nd', 'rd');

相同的function(不返回input),但是我的短小function的爆炸视图更好地理解:

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

有了这个最后的function,只需调用o(121); 和我列出的其他function完全一样。

代码更新#2

本和我一起工作,总共削减了38字节(共83字节):

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

我们不认为它可能会比这更短! 愿意被certificate是错误的,但是。 🙂

希望你们都享受。

在PHP.net中find答案

 <?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'; } ?> 

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

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

或程序上:

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

这当然是因为我select的默认月份(一月份)有31天。

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

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

所以你可以用循环中的date说明符t来计算本月的日子:本月中的天数。

为了进一步简化Lacopo的答案,可以使用以下函数,它使用substr()函数获取数字的最后一位,并将其用作$ ends数组的索引。

 function get_ordinal($number) { $ends=array('th','st','nd','rd','th','th','th','th','th','th'); $last_digit=substr($number, -1, 1); return $number.$ends[$last_digit]; } 

编辑

我上面的函数似乎没有数字以11,12,13结尾,我发布答案时没有注意到。 所以用Lacopo的答案

我喜欢这个小片段

 <?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'; } ?> 

这里