Is there a way in Java to convert an integer to its ordinal name?

Java

Java Problem Overview


I want to take an integer and get its ordinal, i.e.:

1 -> "First"
2 -> "Second"
3 -> "Third"
...

Java Solutions


Solution 1 - Java

If you're OK with 1st, 2nd, 3rd etc, here's some simple code that will correctly handle any integer:

public static String ordinal(int i) {
    String[] suffixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
    switch (i % 100) {
    case 11:
    case 12:
    case 13:
        return i + "th";
    default:
        return i + suffixes[i % 10];

    }
}

Here's some tests for edge cases:

public static void main(String[] args) {
    int[] tests = {0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 100, 101, 102, 103, 104, 111, 112, 113, 114, 1000};
    for (int test : tests) {
        System.out.println(ordinal(test));
    }
}

Output:

0th
1st
2nd
3rd
4th
5th
10th
11th
12th
13th
14th
20th
21st
22nd
23rd
24th
100th
101st
102nd
103rd
104th
111th
112th
113th
114th
1000th

Solution 2 - Java

Using the excellent [ICU4J][1] (there's also an excellent C version) you can also do this and get the Ordinals as plain words;

RuleBasedNumberFormat nf = new RuleBasedNumberFormat(Locale.UK, RuleBasedNumberFormat.SPELLOUT);
for(int i = 0; i <= 30; i++)
{
	System.out.println(i + " -> "+nf.format(i, "%spellout-ordinal"));
}

for example produces

0 -> zeroth
1 -> first
2 -> second
3 -> third
4 -> fourth
5 -> fifth
6 -> sixth
7 -> seventh
8 -> eighth
9 -> ninth
10 -> tenth
11 -> eleventh
12 -> twelfth
13 -> thirteenth
14 -> fourteenth
15 -> fifteenth
16 -> sixteenth
17 -> seventeenth
18 -> eighteenth
19 -> nineteenth
20 -> twentieth
21 -> twenty-first
22 -> twenty-second
23 -> twenty-third
24 -> twenty-fourth
25 -> twenty-fifth
26 -> twenty-sixth
27 -> twenty-seventh
28 -> twenty-eighth
29 -> twenty-ninth
30 -> thirtieth

[1]: http://icu-project.org/apiref/icu4j/com/ibm/icu/text/RuleBasedNumberFormat.html "ICU4J"

Solution 3 - Java

Another solution

public static String ordinal(int i) {
	int mod100 = i % 100;
	int mod10 = i % 10;
	if(mod10 == 1 && mod100 != 11) {
		return i + "st";
	} else if(mod10 == 2 && mod100 != 12) {
		return i + "nd";
	} else if(mod10 == 3 && mod100 != 13) {
		return i + "rd";
	} else {
		return i + "th";
	}
}

Pro: does not require an array to be initialized (less garbage)
Con: not a one-liner...

Solution 4 - Java

I've figured out how to do this in Android in a pretty simple way. All you need to do is to add the dependency to your app's build.gradle file:

implementation "com.ibm.icu:icu4j:53.1"

Next, create this method:

Kotlin:

fun Number?.getOrdinal(): String? {
    if (this == null) {
        return null
    }

    val format = "{0,ordinal}"

    return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        android.icu.text.MessageFormat.format(format, this)
    } else {
        com.ibm.icu.text.MessageFormat.format(format, this)
    }
}

Java:

public static String getNumberOrdinal(Number number) {
        if (number == null) {
            return null;
        }
        
        String format = "{0,ordinal}";

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
            return android.icu.text.MessageFormat.format(format, number);
        } else {
            return com.ibm.icu.text.MessageFormat.format(format, number);
        }
    }

Then, you can simply use it like this:

Kotlin:

val ordinal = 2.getOrdinal()

Java:

String ordinal = getNumberOrdinal(2)

How it works

Starting from Android N (API 24) Android uses icu.text instead of regular java.text (more info here), which already contains internationalized implementation for ordinal numbers. So the solution is obviously simple - to add the icu4j library to the project and use it on versions below the Nougat

Solution 5 - Java

In 1 line:

public static String ordinal(int i) {
    return i % 100 == 11 || i % 100 == 12 || i % 100 == 13 ? i + "th" : i + new String[]{"th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th"}[i % 10];
}

Solution 6 - Java

Bohemians answer is very good but I recommend improving the error handling. With the original version of ordinal if you supply a negative integer an ArrayIndexOutOfBoundsException will be thrown. I think my version below is clearer. I hope the junit is also useful so it is not necessary to visually check the output.

public class FormattingUtils {

	/**
	 * Return the ordinal of a cardinal number (positive integer) (as per common usage rather than set theory).
	 * {@link http://stackoverflow.com/questions/6810336/is-there-a-library-or-utility-in-java-to-convert-an-integer-to-its-ordinal}
	 * 
	 * @param i
	 * @return
	 * @throws {@code IllegalArgumentException}
	 */
	public static String ordinal(int i) {
		if (i < 0) {
			throw new IllegalArgumentException("Only +ve integers (cardinals) have an ordinal but " + i + " was supplied");
		}

		String[] sufixes = new String[] { "th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th" };
		switch (i % 100) {
		case 11:
		case 12:
		case 13:
			return i + "th";
		default:
			return i + sufixes[i % 10];
		}
	}
}


import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;

public class WhenWeCallFormattingUtils_Ordinal {

	@Test
	public void theEdgeCasesAreCovered() {
		int[] edgeCases = { 0, 1, 2, 3, 4, 5, 10, 11, 12, 13, 14, 20, 21, 22, 23, 24, 100, 101, 102, 103, 104, 111, 112,
				113, 114 };
		String[] expectedResults = { "0th", "1st", "2nd", "3rd", "4th", "5th", "10th", "11th", "12th", "13th", "14th",
				"20th", "21st", "22nd", "23rd", "24th", "100th", "101st", "102nd", "103rd", "104th", "111th", "112th",
				"113th", "114th" };

		for (int i = 0; i < edgeCases.length; i++) {
			assertThat(FormattingUtils.ordinal(edgeCases[i])).isEqualTo(expectedResults[i]);
		}
	}

	@Test(expected = IllegalArgumentException.class)
	public void supplyingANegativeNumberCausesAnIllegalArgumentException() {
		FormattingUtils.ordinal(-1);
	}

}

Solution 7 - Java

In Scala for a change,

List(1, 2, 3, 4, 5, 10, 11, 12, 13, 14 , 19, 20, 23, 33, 100, 113, 123, 101, 1001, 1011, 1013, 10011) map {
    case a if (a % 10) == 1 && (a % 100) != 11 => a + "-st"
    case b if (b % 10) == 2 && (b % 100) != 12 => b + "-nd"
    case c if (c % 10) == 3 && (c % 100) != 13 => c + "-rd"
    case e                                     => e + "-th"
  }  foreach println

Solution 8 - Java

private static String getOrdinalIndicator(int number) {
		int mod = number;
		if (number > 13) {
			mod = number % 10;
		}
		switch (mod) {
		case 1:
			return "st";
		case 2:
			return "nd";
		case 3:
			return "rd";
		default:
			return "th";
		}
	}

Solution 9 - Java

I got a long, complicated one but easy to understand the concept

private static void convertMe() {
	
	Scanner in = new Scanner(System.in);
	try {
		System.out.println("input a number to convert: ");
		int n = in.nextInt();
		
		String s = String.valueOf(n);
		//System.out.println(s);
		
		int len = s.length() - 1;
		if (len == 0){
			char lastChar = s.charAt(len);
			if (lastChar == '1'){
				System.out.println(s + "st");
			} else if (lastChar == '2') {
				System.out.println(s + "nd");
			} else if (lastChar == '3') {
				System.out.println(s + "rd");
			} else {
				System.out.println(s + "th");
			}
		} else if (len > 0){
			char lastChar = s.charAt(len);
			char preLastChar = s.charAt(len - 1);
			if (lastChar == '1' && preLastChar != '1'){ //not ...11
				System.out.println(s + "st");
			} else if (lastChar == '2' && preLastChar != '1'){ //not ...12
				System.out.println(s + "nd");
			} else if (lastChar == '3' && preLastChar != '1'){ //not ...13
				System.out.println(s + "rd");
			} else {
				System.out.println(s + "th");
			}
		}
		
		
	} catch(InputMismatchException exception){
		System.out.println("invalid input");
	}
	
	
}

Solution 10 - Java

static String getOrdinal(int input) {
	if(input<=0) {
		throw new IllegalArgumentException("Number must be > 0");
	}
	int lastDigit = input % 10;
	int lastTwoDigit = input % 100;
	if(lastTwoDigit >= 10 && lastTwoDigit <= 20) {
		return input+"th";
	}
	switch (lastDigit) {
	case 1:
		return input+"st";
	case 2:
		return input+"nd";
	case 3:
		return input+"rd";

	default:
		return input+"th";
	}
}

Solution 11 - Java

Just incase if somone looking for a Kotlin extension version :


fun Int.toEnOrdinal(): String {
    val suffixes = arrayListOf("th", "st", "nd", "rd", "th", "th", "th", "th", "th", "th")
    return when (this % 100) {
        11, 12, 13 -> "{$this}th"
        else -> "$this" + suffixes[this % 10]
    }
}

then all you need to do is to call this function on any number like

5.toUKOrdinal() --> 5th

21.toUKOrdinal() --> 21st

etc

Solution 12 - Java

Best and Simple way, Here we go:

import java.util.*;
public class Numbers 
{
	public final static String print(int num)
	{
		num = num%10;
		String str = "";
		switch(num)
		{
		case 1:		
			str = "st";
			break;
		case 2:		
			str = "nd";
			break;
		case 3:		
			str = "rd";
			break;
		default: 
			str = "th";				
		}
		return str;
	}

	public static void main(String[] args) 
	{
		Scanner sc = new Scanner(System.in);
		System.out.print("Enter a number: ");
		int number = sc.nextInt();
		System.out.print(number + print(number));
	}
}

Solution 13 - Java

public static String getOrdinalFor(int value) {
		 int tenRemainder = value % 10;
		 switch (tenRemainder) {
		  case 1:
		   return value+"st";
		  case 2:
		   return value+"nd";
		  case 3:
		   return value+"rd";
		  default:
		   return value+"th";
		 }
		}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionlakemalcomView Question on Stackoverflow
Solution 1 - JavaBohemianView Answer on Stackoverflow
Solution 2 - JavaJFKView Answer on Stackoverflow
Solution 3 - JavaklamannView Answer on Stackoverflow
Solution 4 - JavaAlexander KrolView Answer on Stackoverflow
Solution 5 - JavanvrandowView Answer on Stackoverflow
Solution 6 - JavaMichael ShawView Answer on Stackoverflow
Solution 7 - JavaAbel TerefeView Answer on Stackoverflow
Solution 8 - JavaSwaroop ChippadaView Answer on Stackoverflow
Solution 9 - JavaTuanView Answer on Stackoverflow
Solution 10 - JavaSahebView Answer on Stackoverflow
Solution 11 - Javabastami82View Answer on Stackoverflow
Solution 12 - JavaSiddheshView Answer on Stackoverflow
Solution 13 - JavaTell Me HowView Answer on Stackoverflow