Quiero mostrar los números de la siguiente manera
- 1 como 1er,
- 2 como 2do,
- ...
- 150 como 150
¿Cómo debo encontrar el sufijo ordinal correcto (st, nd, rd o th) para cada número en mi código?
Quiero mostrar los números de la siguiente manera
¿Cómo debo encontrar el sufijo ordinal correcto (st, nd, rd o th) para cada número en mi código?
Respuestas:
$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];
¿Dónde $number
está el número que quieres escribir? Funciona con cualquier número natural.
Como una función:
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);
$abbreviation = ($number)? $number. $ends[$number % 10] : $number;
PHP tiene una funcionalidad incorporada para esto . ¡Incluso maneja la internacionalización!
$locale = 'en_US';
$nf = new NumberFormatter($locale, NumberFormatter::ORDINAL);
echo $nf->format($number);
Tenga en cuenta que esta funcionalidad solo está disponible en PHP 5.3.0 y versiones posteriores.
NumberFomatter file not found
. ¿Cómo resolviste esto?
apt-get install php5-intl
Esto se puede lograr en una sola línea aprovechando una funcionalidad similar en las funciones de fecha / hora integradas de PHP. Humildemente presento:
Solución:
function ordinalSuffix( $n )
{
return date('S',mktime(1,1,1,1,( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));
}
Explicación detallada:
La date()
función incorporada tiene lógica de sufijo para manejar los cálculos del enésimo día del mes. El sufijo se devuelve cuando S
se da en la cadena de formato:
date( 'S' , ? );
Dado que date()
requiere una marca de tiempo (por ?
arriba), vamos a pasar nuestro número entero $n
como el day
parámetro a mktime()
y el uso de los valores ficticia 1
para el hour
, minute
, second
, y month
:
date( 'S' , mktime( 1 , 1 , 1 , 1 , $n ) );
Esto realmente falla con gracia en valores fuera de rango para un día del mes (es decir $n > 31
), pero podemos agregar una lógica en línea simple para limitar $n
a 29:
date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20))*10 + $n%10) ));
El único valor positivo( Mayo de 2017 ) esto falla $n == 0
, pero se soluciona fácilmente agregando 10 en ese caso especial:
date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));
Actualización, mayo de 2017
Como observó @donatJ, lo anterior falla por encima de 100 (por ejemplo, "111"), ya que las >=20
comprobaciones siempre devuelven verdadero. Para restablecer estos cada siglo, agregamos un filtro a la comparación:
date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n%100>=20)+($n==0))*10 + $n%10) ));
¡Simplemente envuélvelo en una función para mayor comodidad y listo!
Aquí hay una frase:
$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);
Probablemente la solución más corta. Por supuesto, puede estar envuelto por una función:
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);
}
Saludos, Paul
EDIT1: Corrección de código para 11 a 13.
EDIT2: Corrección de código para 111, 211, ...
EDITAR3: ahora funciona correctamente también para múltiplos de 10.
de 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;
}
?>
La respuesta simple y fácil será:
$Day = 3;
echo date("S", mktime(0, 0, 0, 0, $Day, 0));
//OUTPUT - rd
Escribí esto para PHP4. Ha estado funcionando bien y es bastante económico.
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';
}
solo necesita aplicar la función dada.
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';
}
Genéricamente, puede usar eso y llamar a 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';
}
?>
Hice una función que no se basa en la date();
función de PHP, ya que no es necesaria, pero también la hice tan compacta y tan corta como creo que es posible actualmente.
El código : (121 bytes en total)
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')));
}
Código más compacto a continuación.
Funciona de la siguiente manera :
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.
Cosas que debes saber sobre esta función :
floor($i)
, round($i)
o ceil($i)
al comienzo de la instrucción de retorno final).format_number($i)
al comienzo de la declaración de devolución final para obtener un número entero separado por comas (si está mostrando miles, millones, etc.).$i
del principio de la declaración de devolución si solo desea devolver el sufijo ordinal sin lo que ingresó.Esta función funciona a partir de PHP 5.2, lanzado en noviembre de 2006, simplemente debido a la sintaxis de matriz corta. Si tiene una versión anterior a esta, ¡actualice ya que está casi una década desactualizada! De lo contrario, simplemente reemplace el en línea ['st', 'nd', 'rd']
con una variable temporal que contengaarray('st', 'nd', 'rd');
.
La misma función (sin devolver la entrada), pero una vista explosionada de mi función corta para una mejor comprensión:
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
}
Actualización de código :
Aquí hay una versión modificada que es 14 bytes completos más cortos (107 bytes en total):
function ordinal($i) {
return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');
}
O, para ser lo más corto posible, 25 bytes más cortos (96 bytes en total):
function o($i){return $i.(($j=abs($i)%100)>10&&$j<14?'th':@['th','st','nd','rd'][$j%10]?:'th');}
Con esta última función, simplemente llame o(121);
y hará exactamente lo mismo que las otras funciones que enumeré.
Actualización de Código # 2 :
Ben y yo trabajamos juntos y lo redujimos en 38 bytes (83 bytes en total):
function o($i){return$i.@(($j=abs($i)%100)>10&&$j<14?th:[th,st,nd,rd][$j%10]?:th);}
¡No creemos que pueda ser más corto que esto! Sin embargo, está dispuesto a demostrar que está equivocado. :)
Espero que todos lo disfruten.
abs()
con módulo%
abs();
elimina el signo negativo que es lo que necesitaba.
Una versión aún más corta para las fechas del mes (hasta 31) en lugar de usar mktime () y no requiere pecl intl:
function ordinal($n) {
return (new DateTime('Jan '.$n))->format('jS');
}
o procesalmente:
echo date_format(date_create('Jan '.$n), 'jS');
Esto funciona, por supuesto, porque el mes predeterminado que elegí (enero) tiene 31 días.
Curiosamente, si lo prueba con febrero (u otro mes sin 31 días), se reinicia antes del final:
...clip...
31st
1st
2nd
3rd
para poder contar hasta los días de este mes con el especificador de fecha t
en su ciclo: número de días en el mes.
Encontré una respuesta en 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';
}
?>
Aquí hay otra versión muy corta que usa las funciones de fecha. Funciona para cualquier número (no limitado por los días del mes) y tiene en cuenta que * 11th * 12th * 13th no sigue el formato * 1st * 2nd * 3rd.
function getOrdinal($n)
{
return $n . date_format(date_create('Jan ' . ($n % 100 < 20 ? $n % 20 : $n % 10)), 'S');
}
Aprecio este pequeño fragmento
<?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';
}
?>