Built-in way to convert Integer to Ordinal String

The coolest way is to check the answer to this question by David Carraher. I am shamelessly stealing his code here to write a function that gives you rules for up to maxNumber:

ordinalRule[maxNumber_Integer] /; maxNumber > 0 := 
  Block[{p},
    Thread[
      Function[{x}, 
        x -> StringSplit[SpokenString[p[[#]]]][[2]] &[x] // Quiet] /@ Range[maxNumber]
  ]];

For example:

ordinalRule[100]

(*out*){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"}

I don't know whether this counts as built-in though.

----EDIT----

From @Wreach's comment: there is an undocumented built-in (that SpokenString calls when dealing with numbers to ordinals) that does exactly that:

Speak["stackexchange"];
SpokenStringDump`SpeakOrdinal[121]
(*out*) 121st

In v10 I need to call Speak before the relevant function auto-loads.


I noticed only afterwards that you were asking for a built-in method. I'm not certain if you would actually want to rely on an undocumented feature instead of writing your own, since it's not hard.

This requires v10 for StringTemplate. It could be replaced with something else, of course...

Range[120] /.
 { tens_Integer /; Floor[Mod[tens, 100], 10] == 10 :> StringTemplate["`1`th"][tens],
   firsts_Integer /; Mod[firsts, 10] == 1 :> StringTemplate["`1`st"][firsts],
   seconds_Integer /; Mod[seconds, 10] == 2 :> StringTemplate["`1`nd"][seconds],
   thirds_Integer /; Mod[thirds, 10] == 3 :> StringTemplate["`1`rd"][thirds],
   rest_Integer :> StringTemplate["`1`th"][rest] }

(* { "1st", "2nd", "3rd", "4th", "5th", "6th", "7th", "8th", "9th",
     "10th", "11th", "12th", "13th", "14th", "15th", "16th", "17th",
     "18th", "19th", "20th", "21st", "22nd", "23rd", "24th", "25th",
     "26th", "27th", "28th", "29th", "30th", "31st", "32nd", "33rd",
     "34th", "35th", "36th", "37th", "38th", "39th", "40th", "41st",
     "42nd", "43rd", "44th", "45th", "46th", "47th", "48th", "49th",
     "50th", "51st", "52nd", "53rd", "54th", "55th", "56th", "57th",
     "58th", "59th", "60th", "61st", "62nd", "63rd", "64th", "65th",
     "66th", "67th", "68th", "69th", "70th", "71st", "72nd", "73rd",
     "74th", "75th", "76th", "77th", "78th", "79th", "80th", "81st",
     "82nd", "83rd", "84th", "85th", "86th", "87th", "88th", "89th",
     "90th", "91st", "92nd", "93rd", "94th", "95th", "96th", "97th",
     "98th", "99th", "100th", "101st", "102nd", "103rd", "104th", 
     "105th", "106th", "107th", "108th", "109th", "110th", "111th",
     "112th", "113th", "114th", "115th", "116th", "117th", "118th",
     "119th", "120th" } *)

A brute force but very simple approach (no undocumented functions needed) that I think will work with any version of Mathematica.

ordinalRule[n_Integer /; Mod[n, 100] == 11] := generalRule[n]
ordinalRule[n_Integer /; Mod[n, 100] == 12] := generalRule[n]
ordinalRule[n_Integer /; Mod[n, 100] == 13] := generalRule[n]
ordinalRule[n_Integer /; Mod[n, 10] == 1] = specialRule1[n];
ordinalRule[n_Integer /; Mod[n, 10] == 2] = specialRule2[n];
ordinalRule[n_Integer /; Mod[n, 10] == 3] = specialRule3[n];
ordinalRule[n_Integer] = generalRule[n];
specialRule1[n_] := n -> (ToString[n] <> "st")
specialRule2[n_] := n -> (ToString[n] <> "nd")
specialRule3[n_] := n -> (ToString[n] <> "rd")
generalRule[n_] := n -> (ToString[n] <> "th")

ordinalRule /@ Range @ 130
{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", 
 ...
 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", 
 116 -> "116th", 117 -> "117th", 118 -> "118th", 119 -> "119th", 120 -> "120th", 
 121 -> "121st", 122 -> "122nd", 123 -> "123rd", 124 -> "124th", 125 -> "125th", 
 126 -> "126th", 127 -> "127th", 128 -> "128th", 129 -> "129th", 130 -> "130th"}