Does Kotlin have a standard way to format a number as an English ordinal?

2.8k Views Asked by At

In Swift, I can do something like this:

let ordinalFormatter = NumberFormatter()
ordinalFormatter.numberStyle = .ordinal

print(ordinalFormatter.string(from: NSNumber(value: 3))) // 3rd

but I don't see any way to do this so easily in Kotlin. Is there such a way, or will I have to use 3rd-party libraries or write my own?

3

There are 3 best solutions below

6
On BEST ANSWER

Well, it is usually hard to prove that something doesn't exist. But I have never come across any function in kotlin-stdlib that would do this or could be immediately adapted for this. Moreover, kotlin-stdlib doesn't seem to contain anything locale-specific (which number ordinals certainly are).

I guess you should actually resort to some third-party software or implement your own solution, which might be something as simple as this:

fun ordinalOf(i: Int) {
    val iAbs = i.absoluteValue // if you want negative ordinals, or just use i
    return "$i" + if (iAbs % 100 in 11..13) "th" else when (iAbs % 10) {
        1 -> "st"
        2 -> "nd"
        3 -> "rd"
        else -> "th"
    }
}

Also, solutions in Java: (here)

0
On
fun Int.toOrdinalNumber(): String {
    if (this in 11..13) {
        return "${this}th"
    }

    return when (this % 10) {
        1 -> "${this}st"
        2 -> "${this}nd"
        3 -> "${this}rd"
        else -> "${this}th"
    }
}

In this code, the In this code, the getOrdinalNumber extension function is added to the Int class. It first checks if the number is in the range of 11 to 13 because in these cases, the ordinal is always "th." For other cases, it checks the last digit of the number and appends "st," "nd," or "rd" accordingly. If none of these conditions match, it appends "th." extension function is added to the Int class. It first checks if the number is in the range of 11 to 13 because in these cases, the ordinal is always "th." For other cases, it checks the last digit of the number and appends "st," "nd," or "rd" accordingly. If none of these conditions match, it appends "th."

1
On

Here's my take, a variant of @hotkey's solution:

    fun Int.ordinal() = "$this" + when {
        (this % 100 in 11..13) -> "th"
        (this % 10) == 1 -> "st"
        (this % 10) == 2 -> "nd"
        (this % 10) == 3 -> "rd"
        else -> "th"
    }

Invoke with e.g. 13.ordinal().