16 ответов:
$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 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 имеет встроенный функционал для этого. Он даже обрабатывает интернационализацию!
$locale = 'en_US'; $nf = new NumberFormatter($locale, NumberFormatter::ORDINAL); echo $nf->format($number);обратите внимание, что эта функция доступна только в PHP 5.3.0 и выше.
это можно сделать в одной строке, используя аналогичную функциональность во встроенных функциях даты/времени PHP. Я смиренно подчиняюсь:
устранение:
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как доmktime()и использовать логические значения1наhour,minute,secondиmonth:date( 'S' , mktime( 1 , 1 , 1 , 1 , $n ) );это на самом деле не удается изящно на значения вне диапазона в течение дня месяца (т. е.
$n > 31) но мы можем добавить некоторую простую встроенную логику в cap$nна 29:date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20))*10 + $n%10) ));
единственный положительный значение(мая 2017) это не удается на is$n == 0, но это легко исправить, добавив 10 в этом специальном случае:date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n>=20)+($n==0))*10 + $n%10) ));Обновление, Май 2017
как заметил @donatJ, выше не выше 100 (например, "111st"), так как
>=20проверки всегда возвращают true. Чтобы сбросить их каждый век, мы добавляем фильтр для сравнения:date( 'S', mktime( 1, 1, 1, 1, ( (($n>=10)+($n%100>=20)+($n==0))*10 + $n%10) ));просто оберните его в функцию для удобства и вперед!
от 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); }С уважением, Пол
EDIT1: исправление кода для 11-13.
EDIT2: исправление кода для 111, 211, ...
EDIT3: теперь он работает правильно и для кратных 10.
Я написал это для 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'; } ?>
вам просто нужно применить данную функцию.
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-й и т.д. для подростков цифры, как и ожидалось.
- он не проверяет десятичные знаки, но оставит их на месте (используйте
floor($i),round($i)илиceil($i)в начале заключительного оператора возврата).- вы также можете добавить
format_number($i)в начале последнего оператора return, чтобы получить целое число через запятую (если вы показываете тысячи, миллионы и т. д.).- вы могли бы просто удалить
$iС начала инструкции return, если вы хотите только вернуть порядковый суффикс без того, что вы вводите.эта функция работает начиная с PHP 5.2, выпущенного в ноябре 2006 года, исключительно из-за синтаксиса короткого массива. Если у вас есть версия до этого, то, пожалуйста, обновите, потому что вы почти десять лет устарели! В противном случае, просто замените in-line
['st', 'nd', 'rd']С временной переменной содержащийarray('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:
Бен и я работал вместе и сократил его на 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');это работает, конечно, потому что месяц по умолчанию я выбрал (январь) имеет 31 дней.
интересно, что если вы попробуете его с февраля (или другого месяца без 31 дней), он перезапускается до конца:
...clip... 31st 1st 2nd 3rdтаким образом, вы можете рассчитывать до дней этого месяца с помощью спецификатора даты
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]; }Edit
моя вышеприведенная функция, похоже, не работает для чисел, заканчивающихся 11, 12, 13, которые я не заметил при отправке ответа. Поэтому используйте ответ Лакопо.
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; }
вот еще одна очень короткая версия, использующая функции даты. Он работает для любого числа (не ограниченного днями месяца) и учитывает, что *11th *12th *13th не соответствует формату *1st *2nd *3rd.
function getOrdinal($n) { return $n . date_format(date_create('Jan ' . ($n % 100 < 20 ? $n % 20 : $n % 10)), 'S'); }
Мне нравится этот маленький фрагмент
<?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'; } ?>
Comments