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

我希望按如下方式显示数字

  • 1号作为1号,
  • 2号作为2号,
  • ...,
  • 第150个。

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

81877 次浏览

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

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

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的代码更正。

编辑2:111,211,..。

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

PHP 为这个 提供了内置的功能。它甚至可以处理国际化!

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

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

这是我为 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';
}

这可以通过利用 PHP 内置的 date/time 函数中的类似功能在一行中完成。我谦卑地提议:

解决方案:

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参数传递给 ?0,并对 hourminutesecondmonth使用虚拟的 1值:

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

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

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

这个值唯一的正值 (二零一七年五月)是 $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。为了每个世纪重新设置这些数据,我们在比较中加入了一个过滤器:

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

只要将它包装在一个方便的函数中就可以了!

通常,您可以使用它并调用 Echo get _ place _ 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';
}
?>

你只需要应用给定的函数。

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


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();函数,因为它是不必要的,但也使它尽可能紧凑和短,因为我认为目前是可能的。

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

关于这个函数需要了解的内容 :

  • 它处理负整数和处理正整数一样,并保持符号。
  • 对于预期的 十几岁数字,它返回11、12、13、811、812、813等。
  • 它不检查小数,但会保留它们(在最终 return 语句的开头使用 floor($i)round($i)ceil($i))。
  • 您还可以在最后返回语句的开头添加 format_number($i),以获得逗号分隔的整数(如果显示的是数千、数百万等)。
  • 如果只想返回序数后缀而不想输入内容,那么可以从 return 语句的开头删除 $i

这个函数从2006年11月发布的 PHP 5.2开始工作,纯粹是因为短数组语法。如果你有一个版本之前,然后请升级,因为你几乎十年过时!否则,只需用包含 array('st', 'nd', 'rd');的临时变量替换行内 ['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);}

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

希望你们都喜欢。

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

一个更短的版本,用于显示月份中的日期(最多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来计算这个月的天数: 这个月的天数。

简单明了的答案是:

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


//OUTPUT - rd
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;
}

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

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

这是正确的解决方案

$numberFormatter = new NumberFormatter('en_US', NumberFormatter::ORDINAL);


echo $numberFormatter->format(11);