Afficher les nombres avec suffixe ordinal en PHP

Je veux afficher les nombres comme suit

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

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

119
demandé sur ArK 2010-06-24 16:40:30

16 réponses

À Partir 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 nombre que vous souhaitez écrire. Fonctionne avec n'importe quel nombre naturel.

En 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);
240
répondu Iacopo 2015-04-08 15:13:34

PHP a des fonctionnalités intégrées 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é n'est disponible qu'en PHP 5.3.0 et versions ultérieures.

110
répondu Jeremy Kauffman 2012-01-24 15:24:22

Cela peut être accompli en une seule ligne en tirant parti de fonctionnalités similaires dans les fonctions 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:

Le haut-date() la fonction a une logique de suffixe pour gérer les calculs du nième jour du mois. Le suffixe est retourné lorsque S est donné dans la chaîne de format:

date( 'S' , ? );

Puisque date() nécessite un horodatage (pour ? ci-dessus), nous allons passer notre integer $n comme day paramètre mktime() et l'utilisation des valeurs factices de 1 pour le hour, minute, second, et month:

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

Cela échoue en fait gracieusement sur les valeurs hors plage pour un jour du mois (c'est-à-dire $n > 31) mais nous pouvons ajouter une simple logique en ligne à cap $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 is $n == 0, mais c'est facilement corrigé en ajoutant 10 dans cette spéciale cas:

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 "111st"), puisque les vérifications >=20 renvoient toujours true. 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) ));

Il suffit de l'envelopper dans une fonction pour plus de commodité et vous partez!

14
répondu Andrew Kozak 2017-05-05 20:09:28

À Partir 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
répondu John Boker 2010-06-24 12:42:08

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 sûr ê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 pour 11 à 13.

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

EDIT3: maintenant, cela fonctionne correctement aussi pour les multiples de 10.

13
répondu Paul 2016-09-06 20:57:58

J'ai écrit ceci pour PHP4. Il travaille sur ok et c'est assez é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
répondu iletras 2016-12-20 02:54:50

Réponse Simple et facile sera:

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

//OUTPUT - rd
6
répondu WhiteHorse 2015-12-28 19:49:22

Génériquement, 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
répondu Uzair Bin Nisar 2012-11-26 12:11:48

Vous avez juste besoin 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
répondu ChintanThummar 2014-08-18 12:27:12

J'ai fait une fonction qui ne repose pas sur la fonction date(); de PHP car ce n'est pas nécessaire, mais qui l'a également rendue aussi compacte et aussi courte que je pense actuellement possible.

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.

Il 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.

Trucs à savoir 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 11ème, 12ème, 13ème, 811th, 812th, 813th, etc. pour les numéros-teen comme prévu.
  • , Il ne vérifie pas les décimales, mais laisse en place (utilisation floor($i), round($i), ou ceil($i) au début de la dernière instruction de retour).
  • vous pouvez également ajouter format_number($i) au début de l'instruction return finale 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 du retour instruction si vous voulez seulement retourner le suffixe ordinal sans ce que vous entrez.

Cette fonction fonctionne à partir de PHP 5.2 publié en novembre 2006 uniquement à cause de la syntaxe du tableau court. Si vous avez une version avant cela, alors veuillez mettre à jour parce que vous êtes presque une décennie obsolète! A défaut, remplacez simplement la ligne ['st', 'nd', 'rd'] par une variable temporaire contenant array('st', 'nd', 'rd');.

La même fonction (sans renvoyer l'entrée), mais une vue éclatée de ma fonction courte 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 de 14 Octets entiers plus courte (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 étant 25 octets plus court (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 cela fera exactement la même chose que les autres fonctions que j'ai énumérées.

Mise À Jour Du Code #2:

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

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 être plus court que ça! Prêt à être prouvé faux, cependant. :)

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

1
répondu nxasdf 2017-05-23 11:47:30

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
répondu mysticmo 2015-09-21 08:31:34

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 parce que le mois par défaut que j'ai choisi (janvier) a 31 jours.

Assez intéressant 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

Ainsi, vous pouvez compter jusqu'à ce que les jours de ce mois avec le spécificateur de date t dans votre boucle: nombre de jours dans mois.

0
répondu Dan Dart 2015-11-27 09:59:53

Pour simplifier encore la réponse de Lacopo, vous pouvez utiliser la fonction suivante qui obtient le dernier chiffre du nombre en utilisant 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 nombres se terminant par 11, 12, 13 que je n'ai pas remarqué en postant la réponse. Alors, utilisez la réponse de Lacopo.

0
répondu Bilal Shareef 2016-01-25 12:48:45
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;
  }
0
répondu xyz 2018-01-17 11:42:28

Voici une autre version très courte utilisant les fonctions de date. Il fonctionne pour n'importe quel nombre (pas contraint par les jours du mois) et prend en compte que *11th *12th *13th ne suit pas le format *1st *2nd *3rd.

function getOrdinal($n)
{
    return $n . date_format(date_create('Jan ' . ($n % 100 < 20 ? $n % 20 : $n % 10)), 'S');
}
0
répondu Claire Matthews 2018-07-06 22:55:46

J'aime ce petit extrait

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

?>

ICI

-1
répondu niksmac 2014-03-25 09:23:38