web-dev-qa-db-fra.com

Afficher les nombres avec suffixe ordinal dans PHP

Je veux afficher les nombres comme suit

  • 1 comme 1er,
  • 2 en 2ème,
  • ...
  • 150 comme 150ème.

Comment trouver le suffixe ordinal correct (st, nd, rd ou th) pour chaque numéro de mon code?

124
ArK

de 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 est le numéro que vous voulez écrire. Fonctionne avec n'importe quel nombre naturel.

En tant que fonction:

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

PHP a une fonctionnalité intégrée pour cela . Il gère même l'internationalisation!

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

Notez que cette fonctionnalité est uniquement disponible dans PHP 5.3.0 et versions ultérieures.

113
Jeremy Kauffman

Cela peut être accompli en une seule ligne en exploitant des fonctionnalités similaires dans les fonctions de date/heure intégrées de PHP. Je soumets humblement:

Solution:

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

Explication détaillée:

La fonction date() intégrée possède une logique de suffixe pour le traitement des calculs du nième jour du mois. Le suffixe est renvoyé lorsque S est donné dans la chaîne de formatage:

date( 'S' , ? );

Puisque date() nécessite un horodatage (pour ? ci-dessus), nous passons notre entier $n en tant que paramètre day à mktime() et utilisons des valeurs factices de 1 pour hour, minute, second et month:

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

En fait, cela échoue gracieusement sur les valeurs hors limites pour un jour du mois (c'est-à-dire $n > 31) mais nous pouvons ajouter une logique simple en ligne pour plafonner $n à 29:

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

La seule valeur positive(Mai 2017) cela échoue sur $n == 0, mais cela est facilement corrigé en ajoutant 10 dans ce cas spécial:

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

Mise à jour, mai 2017

Comme observé par @donatJ, ce qui précède échoue au-dessus de 100 (par exemple, "111ème"), car les vérifications >=20 retournent toujours à Vrai. Pour les réinitialiser tous les siècles, nous ajoutons un filtre à la comparaison:

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

Enveloppez-le simplement dans une fonction pour plus de commodité et c'est parti!

16
Andrew Kozak

Voici un one-liner:

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

Probablement la solution la plus courte. Peut bien entendu être enveloppé par une fonction:

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

Cordialement, .__ Paul

EDIT1: Correction du code de 11 à 13.

EDIT2: Correction du code pour 111, 211, ...

EDIT3: Maintenant, cela fonctionne aussi pour des multiples de 10.

14
Paul

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;
}
?> 
13
John Boker

J'ai écrit ceci pour PHP4 . Ça fonctionne bien et c'est très économique.

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

La réponse simple et facile sera:

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

//OUTPUT - rd
6
WhiteHorse

il vous suffit d’appliquer une fonction donnée.

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

Généralement, vous pouvez l'utiliser et appeler 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';
}
?>
3
Uzair Bin Nisar

J'ai créé une fonction qui ne s'appuie pas sur la fonction date(); de PHP car elle n'est pas nécessaire, mais l'a aussi compacte et aussi courte que possible, à mon avis.

Le code: (121 octets au 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')));
}

Code plus compact ci-dessous.

Cela fonctionne comme suit:

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.

Informations à connaître sur cette fonction:

  • Il traite les entiers négatifs de la même manière que les entiers positifs et conserve le signe.
  • Il retourne les 11, 12, 13, 811, 812, 813, etc. pour les -14 nombres prévus.
  • Il ne vérifie pas les nombres décimaux, mais les laisse en place (utilisez floor($i), round($i) ou ceil($i) au début de la déclaration finale).
  • Vous pouvez également ajouter format_number($i) au début de la dernière instruction return pour obtenir un entier séparé par des virgules (si vous affichez des milliers, des millions, etc.).
  • Vous pouvez simplement supprimer le $i depuis le début de l'instruction return si vous souhaitez uniquement renvoyer le suffixe ordinal sans ce que vous avez entré.

Cette fonction fonctionne à partir de PHP 5.2 publié en novembre 2006 uniquement à cause de la syntaxe de tableau abrégé. Si vous avez une version antérieure à celle-ci, veuillez effectuer une mise à niveau car vous êtes presque obsolète depuis une décennie! Sinon, il suffit de remplacer le ['st', 'nd', 'rd'] en ligne par une variable temporaire contenant array('st', 'nd', 'rd');.

La même fonction (sans retourner l'entrée), mais une vue éclatée de ma courte fonction pour une meilleure compréhension:

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
}

Mise à jour du code:

Voici une version modifiée plus courte de 14 octets (107 octets au total):

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

Ou aussi court que possible de 25 octets de moins (96 octets au total):

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

Avec cette dernière fonction, appelez simplement o(121); et il fera exactement la même chose que les autres fonctions que j'ai énumérées.

Mise à jour du code n ° 2:

Ben et j'ai travaillé ensemble et l'avons réduit de 38 octets (total de 83 octets):

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

Nous ne pensons pas que cela puisse éventuellement être plus court! Vouloir se tromper, cependant. :)

J'espère que vous apprécierez tous.

2
nxasdf
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;
  }
1
xyz

Pour simplifier davantage la réponse de Lacopo, vous pouvez utiliser la fonction suivante qui obtient le dernier chiffre du nombre à l'aide de la fonction substr () et l'utilise comme index du tableau $ 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];
}

Modifier

Ma fonction ci-dessus semble échouer pour les numéros se terminant par 11, 12, 13 que je n'ai pas remarqués lors de l'affichage de la réponse. Alors utilisez la réponse de Lacopo.

0
Bilal Shareef

Voici une autre version très courte utilisant les fonctions de date. Cela fonctionne pour n'importe quel nombre (non limité par les jours du mois) et prend en compte que * 11 * * 12 * 13 ne suit pas le * 1er * 2ème * 3ème format.

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

Trouvé une réponse dans 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';
}
?>
0
mysticmo

Une version encore plus courte pour les dates du mois (jusqu'à 31) au lieu d'utiliser mktime () et ne nécessitant pas pecl intl:

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

ou procéduralement:

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

Cela fonctionne bien sûr car le mois par défaut que j'ai choisi (janvier) a 31 jours.

Curieusement, si vous l’essayez avec février (ou un autre mois sans 31 jours), il redémarre avant la fin:

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

vous pouvez donc compter le nombre de jours du mois avec le spécificateur de date t dans votre boucle: nombre de jours du mois.

0
Dan Dart