Agregue el sufijo st, nd, rd y th (ordinal) a un número

150

Me gustaría generar dinámicamente una cadena de texto basada en un día actual. Entonces, por ejemplo, si es el día 1, me gustaría que mi código genere = "Es el <dynamic> 1 * <dynamic string> st </ dynamic string> * </dynamic>".

Hay 12 días en total, así que he hecho lo siguiente:

  1. He configurado un bucle for que recorre los 12 días.

  2. En mi html, le he dado a mi elemento una identificación única con la que apuntarlo, vea a continuación:

    <h1 id="dynamicTitle" class="CustomFont leftHeading shadow">On The <span></span> <em>of rest of generic text</em></h1>
  3. Luego, dentro de mi bucle for, tengo el siguiente código:

    $("#dynamicTitle span").html(i);
    var day = i;
    if (day == 1) {
        day = i + "st";
    } else if (day == 2) {
        day = i + "nd"
    } else if (day == 3) {
        day = i + "rd"
    }

ACTUALIZAR

Este es el ciclo for completo según lo solicitado:

$(document).ready(function () {
    for (i = 1; i <= 12; i++) {
        var classy = "";
        if (daysTilDate(i + 19) > 0) {
            classy = "future";
            $("#Day" + i).addClass(classy);
            $("#mainHeading").html("");
            $("#title").html("");
            $("#description").html("");
        } else if (daysTilDate(i + 19) < 0) {
            classy = "past";
            $("#Day" + i).addClass(classy);
            $("#title").html("");
            $("#description").html("");
            $("#mainHeading").html("");
            $(".cta").css('display', 'none');
            $("#Day" + i + " .prizeLink").attr("href", "" + i + ".html");
        } else {
            classy = "current";
            $("#Day" + i).addClass(classy);
            $("#title").html(headings[i - 1]);
            $("#description").html(descriptions[i - 1]);
            $(".cta").css('display', 'block');
            $("#dynamicImage").attr("src", ".." + i + ".jpg");
            $("#mainHeading").html("");
            $(".claimPrize").attr("href", "" + i + ".html");
            $("#dynamicTitle span").html(i);
            var day = i;
            if (day == 1) {
                day = i + "st";
            } else if (day == 2) {
                day = i + "nd"
            } else if (day == 3) {
                day = i + "rd"
            } else if (day) {
            }
        }
    }
Antonio Vasilev
fuente
1
Si su código fuente es lo suficientemente corto, ¿le importaría publicar todo y decir exactamente qué está mal o qué le confunde?
RonaldBarzell
¿Qué es lo que su código hace / no hace actualmente? No dijiste claramente qué está pasando mal.
Puntiagudo
Supongo que el código que se muestra es el contenido de un ifbloque que el bucle contiene. Mostrar más códigos ....
MrCode
@MrCode - Sí, estás en lo correcto. He actualizado la publicación para incluir todo el bucle for. ¡Espero que esto lo aclare!
Antonio Vasilev
ordenado y funciona bien.
Dan Jay

Respuestas:

345

Las reglas son las siguientes:

  • st se usa con números que terminan en 1 (por ejemplo, primero, pronunciado primero)
  • nd se usa con números que terminan en 2 (p. ej., 92, pronunciado noventa segundos)
  • rd se usa con números que terminan en 3 (p. ej. 33º, pronunciado trigésimo tercero)
  • Como excepción a las reglas anteriores, todos los números "adolescentes" que terminan con 11, 12 o 13 usan -th (p. Ej. 11, pronunciado undécimo, 112, pronunciado ciento [y] duodécimo)
  • th se usa para todos los demás números (por ejemplo, noveno, pronunciado noveno).

El siguiente código JavaScript (reescrito en junio '14) logra esto:

function ordinal_suffix_of(i) {
    var j = i % 10,
        k = i % 100;
    if (j == 1 && k != 11) {
        return i + "st";
    }
    if (j == 2 && k != 12) {
        return i + "nd";
    }
    if (j == 3 && k != 13) {
        return i + "rd";
    }
    return i + "th";
}

Salida de muestra para números entre 0-115:

  0  0th
  1  1st
  2  2nd
  3  3rd
  4  4th
  5  5th
  6  6th
  7  7th
  8  8th
  9  9th
 10  10th
 11  11th
 12  12th
 13  13th
 14  14th
 15  15th
 16  16th
 17  17th
 18  18th
 19  19th
 20  20th
 21  21st
 22  22nd
 23  23rd
 24  24th
 25  25th
 26  26th
 27  27th
 28  28th
 29  29th
 30  30th
 31  31st
 32  32nd
 33  33rd
 34  34th
 35  35th
 36  36th
 37  37th
 38  38th
 39  39th
 40  40th
 41  41st
 42  42nd
 43  43rd
 44  44th
 45  45th
 46  46th
 47  47th
 48  48th
 49  49th
 50  50th
 51  51st
 52  52nd
 53  53rd
 54  54th
 55  55th
 56  56th
 57  57th
 58  58th
 59  59th
 60  60th
 61  61st
 62  62nd
 63  63rd
 64  64th
 65  65th
 66  66th
 67  67th
 68  68th
 69  69th
 70  70th
 71  71st
 72  72nd
 73  73rd
 74  74th
 75  75th
 76  76th
 77  77th
 78  78th
 79  79th
 80  80th
 81  81st
 82  82nd
 83  83rd
 84  84th
 85  85th
 86  86th
 87  87th
 88  88th
 89  89th
 90  90th
 91  91st
 92  92nd
 93  93rd
 94  94th
 95  95th
 96  96th
 97  97th
 98  98th
 99  99th
100  100th
101  101st
102  102nd
103  103rd
104  104th
105  105th
106  106th
107  107th
108  108th
109  109th
110  110th
111  111th
112  112th
113  113th
114  114th
115  115th
Salman A
fuente
1
También funcionó realmente bien para la mía: dateString = monthNames [newValue.getUTCMonth ()] + "" + numberSuffix (newValue.getUTCDate ()) + "," + newValue.getUTCFullYear ();
Michael J. Calkins
9
Esto no maneja las excepciones para los tres números "adolescentes" correctamente. Por ejemplo, los números 111, 112y 113debería resultar en "111th", "112th"y "113th"respectivamente, no el "111st", "112nd"y "113rd"producido por la función como codificado actualmente.
Martineau
3
Esta respuesta parece haber evolucionado perfectamente. Gracias a todos los contribuyentes.
Lonnie Best
77
Lo identifiqué como un lambda ES6 sin ninguna razón real:n=>n+(n%10==1&&n%100!=11?'st':n%10==2&&n%100!=12?'nd':n%10==3&&n%100!=13?'rd':'th')
Camilo Martin
1
@Anomalía curiosamente, después de ~ π / 2 años después todavía puedo leerlo.
Camilo Martin
211

De Shopify

function getNumberWithOrdinal(n) {
  var s = ["th", "st", "nd", "rd"],
      v = n % 100;
  return n + (s[(v - 20) % 10] || s[v] || s[0]);
}

[-4,-1,0,1,2,3,4,10,11,12,13,14,20,21,22,100,101,111].forEach(
  n => console.log(n + ' -> ' + getNumberWithOrdinal(n))
);

Fizer Khan
fuente
22
¡Agregar una explicación puede hacer que sea una mejor respuesta!
Pugazh
55
@Pugazh A. encuentre s [v% 10] if> = 20 (20th ... 99th), B. si no se encuentra, intente s [v] (0th..3rd), C. si aún no se encuentra, use s [0] (4 ... 19)
Sheepy
44
¿Por qué el doble obtiene el nombre de la función?
Gisheri
46

Enfoque mínimo de una línea para sufijos ordinales

function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}

(esto es para enteros positivos, ver más abajo para otras variaciones)

Explicación

Comience con una matriz con los sufijos ["st", "nd", "rd"]. Queremos asignar enteros que terminen en 1, 2, 3 (pero que no terminen en 11, 12, 13) a los índices 0, 1, 2.

Otros números enteros (incluidos los que terminan en 11, 12, 13) se pueden asignar a cualquier otra cosa; los índices que no se encuentran en la matriz se evaluarán undefined. Esto es falso en javascript y con el uso de lógico o ( || "th") la expresión regresará "th"para estos enteros, que es exactamente lo que queremos.

La expresión ((n + 90) % 100 - 10) % 10 - 1hace el mapeo. Desglosándolo:

  • (n + 90) % 100: Esta expresión toma el entero de entrada - 10 mod 100, mapeo 10 a 0, ... 99 a 89, 0 a 90, ..., 9 a 99. Ahora los enteros que terminan en 11, 12, 13 están en la parte inferior final (asignado a 1, 2, 3).
  • - 10: Ahora 10 se asigna a −10, 19 a −1, 99 a 79, 0 a 80, ... 9 a 89. Los enteros que terminan en 11, 12, 13 se asignan a enteros negativos (−9, −8, −7).
  • % 10: Ahora todos los enteros que terminan en 1, 2 o 3 se asignan a 1, 2, 3. Todos los demás enteros se asignan a otra cosa (11, 12, 13 todavía se asignan a −9, −8, −7).
  • - 1: Restar uno da el mapeo final de 1, 2, 3 a 0, 1, 2.

Verificando que funciona

function nth(n){return["st","nd","rd"][((n+90)%100-10)%10-1]||"th"}

//test integers from 1 to 124
for(var r = [], i = 1; i < 125; i++) r.push(i + nth(i));

//output result
document.getElementById('result').innerHTML = r.join('<br>');
<div id="result"></div>

Variaciones

Permitir enteros negativos:

function nth(n){return["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"}

En la sintaxis de flecha gorda ES6 (función anónima):

n=>["st","nd","rd"][(((n<0?-n:n)+90)%100-10)%10-1]||"th"

Actualizar

Una alternativa aún más corta para enteros positivos es la expresión

[,'st','nd','rd'][n%100>>3^1&&n%10]||'th'

Ver esta publicación para una explicación.

Actualización 2

[,'st','nd','rd'][n/10%10^1&&n%10]||'th'
Tomás Langkaas
fuente
3
elegante. mi favorito.
Guy Mograbi
10

Intl.PluralRules, el método estándar .

Solo me gustaría dejar la forma canónica de hacer esto aquí, ya que nadie parece saberlo.

const english_ordinal_rules = new Intl.PluralRules("en", {type: "ordinal"});
const suffixes = {
	one: "st",
	two: "nd",
	few: "rd",
	other: "th"
};
function ordinal(number) {
	const suffix = suffixes[english_ordinal_rules.select(number)];
	return (number + suffix);
}

const test = Array(201)
	.fill()
	.map((_, index) => index - 100)
	.map(ordinal)
	.join(" ");
console.log(test);

Константин Ван
fuente
1
Esta es la única buena solución general, ya que es la única respuesta aquí que maneja números negativos.
RobG
7

¿Solo tienes 12 días? Estaría tentado a hacerlo solo una simple matriz de búsqueda:

var suffixes = ['','st','nd','rd','th','th','th','th','th','th','th','th','th'];

luego

var i = 2;
var day = i + suffixes[i]; // result: '2nd'

o

var i = 8;
var day = i + suffixes[i]; // result: '8th'
Jamiec
fuente
Gracias, esto resolvió mi problema. No pude obtener el sufijo para que coincida con el día, así que simplemente llené la matriz con los números y el sufijo que funciona perfectamente. Entonces simplemente lo llamé como$("#dynamicTitle span").html(suffix[i-1]);
Antonio Vasilev
7

Al dividir el número en una matriz e invertirlo, podemos verificar fácilmente los últimos 2 dígitos del número usando array[0]y array[1].

Si un número está en la adolescencia array[1] = 1, requiere "th".

function getDaySuffix(num)
{
    var array = ("" + num).split("").reverse(); // E.g. 123 = array("3","2","1")

    if (array[1] != "1") { // Number is in the teens
        switch (array[0]) {
            case "1": return "st";
            case "2": return "nd";
            case "3": return "rd";
        }
    }

    return "th";
}
mella
fuente
Esto es perfecto. ¡Gracias!
Jason
Debe excluir 11, 12, 13
psx
2
@psx Para eso es la condición en la línea 5.
nick
4
function getSuffix(n) {return n < 11 || n > 13 ? ['st', 'nd', 'rd', 'th'][Math.min((n - 1) % 10, 3)] : 'th'}
Johnny
fuente
Una bonita y pequeña oneliner, sólo un poco difícil de entender
Bryc
Falla donde n == 0 debido a una n - 1parte (devuelve indefinido). También falla para números mayores que 110, por ejemplo, getSuffix(111)devuelve "st". Resuelve el problema del OP donde los números son del 1 al 12, pero no es una solución general. :-(
RobG
2

Escribí esta función para resolver este problema:

// this is for adding the ordinal suffix, turning 1, 2 and 3 into 1st, 2nd and 3rd
Number.prototype.addSuffix=function(){
    var n=this.toString().split('.')[0];
    var lastDigits=n.substring(n.length-2);
    //add exception just for 11, 12 and 13
    if(lastDigits==='11' || lastDigits==='12' || lastDigits==='13'){
        return this+'th';
    }
    switch(n.substring(n.length-1)){
        case '1': return this+'st';
        case '2': return this+'nd';
        case '3': return this+'rd';
        default : return this+'th';
    }
};

Con esto, puede poner .addSuffix()cualquier número y obtendrá lo que desea. Por ejemplo:

var number=1234;
console.log(number.addSuffix());
// console will show: 1234th
Jimmery
fuente
Creo que numberen esta cadena var lastDigits=n.substring(number.length-2);debería cambiarse athis
Slava Abakumov
debería ser en nlugar de this, pero gracias por señalar ese error! :)
Jimmery
2

Una versión alternativa de la función ordinal podría ser la siguiente:

function toCardinal(num) {
    var ones = num % 10;
    var tens = num % 100;

    if (tens < 11 || tens > 13) {
        switch (ones) {
            case 1:
                return num + "st";
            case 2:
                return num + "nd";
            case 3:
                return num + "rd";
        }
    }

    return num + "th";
}

Las variables se nombran más explícitamente, usan la convención de casos de camellos y pueden ser más rápidas.

Daniel Harvey
fuente
Sin embargo, esto no funcionará para bases de código localizadas.
Daniel Harvey
1

Escribí esta simple función el otro día. Aunque para una fecha no necesita los números más grandes, esto también atenderá valores más altos (1013, 36021, etc.)

var fGetSuffix = function(nPos){

    var sSuffix = "";

    switch (nPos % 10){
        case 1:
            sSuffix = (nPos % 100 === 11) ? "th" : "st";
            break;
        case 2:
            sSuffix = (nPos % 100 === 12) ? "th" : "nd";
            break;
        case 3:
            sSuffix = (nPos % 100 === 13) ? "th" : "rd";
            break;
        default:
            sSuffix = "th";
            break;
    }

    return sSuffix;
};
Sir Kettle
fuente
1

function ordsfx(a){return["th","st","nd","rd"][(a=~~(a<0?-a:a)%100)>10&&a<14||(a%=10)>3?0:a]}

Vea la versión anotada en https://gist.github.com/furf/986113#file-annotated-js

Corto, dulce y eficiente, como deberían ser las funciones de utilidad. Funciona con cualquier entero / flotante con signo / sin signo. (Aunque no puedo imaginar la necesidad de ordinalizar flotadores)

hndcrftd
fuente
0

Aquí hay otra opción.

function getOrdinalSuffix(day) {
        
   	if(/^[2-3]?1$/.test(day)){
   		return 'st';
   	} else if(/^[2-3]?2$/.test(day)){
   		return 'nd';
   	} else if(/^[2-3]?3$/.test(day)){
   		return 'rd';
   	} else {
   		return 'th';
   	}
        
}
    
console.log(getOrdinalSuffix('1'));
console.log(getOrdinalSuffix('13'));
console.log(getOrdinalSuffix('22'));
console.log(getOrdinalSuffix('33'));

¿Notan la excepción para los adolescentes? ¡Los adolescentes son tan torpes!

Editar: Olvidé los días 11 y 12

Bullyen
fuente
0

Quería proporcionar una respuesta funcional a esta pregunta para complementar la respuesta existente:

const ordinalSuffix = ['st', 'nd', 'rd']
const addSuffix = n => n + (ordinalSuffix[(n - 1) % 10] || 'th')
const numberToOrdinal = n => `${n}`.match(/1\d$/) ? n + 'th' : addSuffix(n)

hemos creado una matriz de valores especiales, lo importante es recordar que las matrices tienen un índice basado en cero, por lo que ordinalSuffix [0] es igual a 'st'.

Nuestra función numberToOrdinal verifica si el número termina en un número adolescente, en cuyo caso agregue el número con 'th' ya que todos los ordinales de números son 'th'. En el caso de que el número no sea un adolescente, pasamos el número a addSuffix que agrega el número al ordinal que se determina si el número menos 1 (porque estamos usando un índice basado en cero) mod 10 tiene un resto de 2 o menos se toma de la matriz, de lo contrario es 'th'.

salida de muestra:

numberToOrdinal(1) // 1st
numberToOrdinal(2) // 2nd
numberToOrdinal(3) // 3rd
numberToOrdinal(4) // 4th
numberToOrdinal(5) // 5th
numberToOrdinal(6) // 6th
numberToOrdinal(7) // 7th
numberToOrdinal(8) // 8th
numberToOrdinal(9) // 9th
numberToOrdinal(10) // 10th
numberToOrdinal(11) // 11th
numberToOrdinal(12) // 12th
numberToOrdinal(13) // 13th
numberToOrdinal(14) // 14th
numberToOrdinal(101) // 101st
Peter McArthur
fuente
0

El viejo que hice para mis cosas ...

function convertToOrdinal(number){
    if (number !=1){
        var numberastext = number.ToString();
        var endchar = numberastext.Substring(numberastext.Length - 1);
        if (number>9){
            var secondfromendchar = numberastext.Substring(numberastext.Length - 1);
            secondfromendchar = numberastext.Remove(numberastext.Length - 1);
        }
        var suffix = "th";
        var digit = int.Parse(endchar);
        switch (digit){
            case 3:
                if(secondfromendchar != "1"){
                    suffix = "rd";
                    break;
                }
            case 2:
                if(secondfromendchar != "1"){
                    suffix = "nd";
                    break;
                }
            case 1:
                if(secondfromendchar != "1"){
                    suffix = "st";
                    break;
                }
            default:
                suffix = "th";
                break;
         }
            return number+suffix+" ";
     } else {
            return;
     }
}
usuario10304
fuente
Agregue alguna descripción sobre el código anterior. Ayudaría mucho más que una pieza de código.
Mathews Sunny
0

Recomiendo encarecidamente la excelente biblioteca de fecha-fns . Rápido, modular, inmutable, funciona con fechas estándar.

import * as DateFns from 'date-fns';

const ordinalInt = DateFns.format(someInt, 'do');

Ver documentos de date-fns: https://date-fns.org/v2.0.0-alpha.9/docs/format

Freewalker
fuente
0

Escribí esta función para números más altos y todos los casos de prueba

function numberToOrdinal(num) {
    if (num === 0) {
        return '0'
    };
    let i = num.toString(), j = i.slice(i.length - 2), k = i.slice(i.length - 1);
    if (j >= 10 && j <= 20) {
        return (i + 'th')
    } else if (j > 20 && j < 100) {
        if (k == 1) {
            return (i + 'st')
        } else if (k == 2) {
            return (i + 'nd')
        } else if (k == 3) {
            return (i + 'rd')
        } else {
            return (i + 'th')
        }
    } else if (j == 1) {
        return (i + 'st')
    } else if (j == 2) {
        return (i + 'nd')
    } else if (j == 3) {
        return (i + 'rd')
    } else {
        return (i + 'th')
    }
}
Chuks de Amaechi
fuente
0

Aquí hay un enfoque ligeramente diferente (no creo que las otras respuestas hagan esto). No estoy seguro de si lo amo o lo odio, ¡pero funciona!

export function addDaySuffix(day: number) { 
  const suffixes =
      '  stndrdthththththththththththththththththstndrdthththththththst';
    const startIndex = day * 2;

    return `${day}${suffixes.substring(startIndex, startIndex + 2)}`;
  }
Dave Cooper
fuente
0

Esto es para una línea y amantes de es6

let i= new Date().getDate 

// I can be any number, for future sake we'll use 9

const j = I % 10;
const k = I % 100;

i = `${i}${j === 1 &&  k !== 11 ? 'st' : j === 2 && k !== 12 ? 'nd' : j === 3 && k !== 13 ? 'rd' : 'th'}`}

console.log(i) //9th

Otra opción para + be number sería:

console.log(["st","nd","rd"][((i+90)%100-10)%10-1]||"th"]

También para deshacerse del prefijo ordinal solo use estos:

console.log(i.parseInt("8th"))

console.log(i.parseFloat("8th"))

siéntase libre de modificar para adaptarse a lo que necesita

Pedro JR
fuente
0

También puedes usar la scales::ordinal()función. Es rápido y fácil de usar.

scales::ordinal(1:12)
## [1] "1st"  "2nd"  "3rd"  "4th"  "5th"  "6th"  "7th"  "8th"  "9th"  "10th" "11th" "12th"
phargart
fuente
-1

Recomiendo encarecidamente esto, es muy fácil y sencillo de leer. Espero que te sirva de ayuda

  • Evita el uso de enteros negativos, es decir, un número menor que 1 y devuelve falso
  • Devuelve 0 si la entrada es 0
function numberToOrdinal(n) {

  let result;

  if(n < 0){
    return false;
  }else if(n === 0){
    result = "0";
  }else if(n > 0){

    let nToString = n.toString();
    let lastStringIndex = nToString.length-1;
    let lastStringElement = nToString[lastStringIndex];

    if( lastStringElement == "1" && n % 100 !== 11 ){
      result = nToString + "st";
    }else if( lastStringElement == "2" && n % 100 !== 12 ){
      result = nToString + "nd";
    }else if( lastStringElement == "3" && n % 100 !== 13 ){
      result = nToString + "rd";
    }else{
      result = nToString + "th";
    }

  }

  return result;
}

console.log(numberToOrdinal(-111));
console.log(numberToOrdinal(0));
console.log(numberToOrdinal(11));
console.log(numberToOrdinal(15));
console.log(numberToOrdinal(21));
console.log(numberToOrdinal(32));
console.log(numberToOrdinal(43));
console.log(numberToOrdinal(70));
console.log(numberToOrdinal(111));
console.log(numberToOrdinal(300));
console.log(numberToOrdinal(101));

SALIDA

false
0
11th
15th
21st
32nd
43rd
70th
111th
300th
101st
an-apluss
fuente
-7

<p>31<sup>st</sup> March 2015</p>

Puedes usar

1<sup>st</sup> 2<sup>nd</sup> 3<sup>rd</sup> 4<sup>th</sup>

para posicionar el sufijo

Vishnu Vikraman
fuente
44
Esto no es lo que pedía el OP
TetraDev