Converting integers to ordinals

When dealing with dates, it's not uncommon to need to convert an integer into an ordinal number (1st, 2nd, 3rd, etc.). While making improvements to Mango recently I wrote a function to do this, first in Python, later in JavaScript.

Python

def ordinal(n):
    if 10 < n < 14: return u'%sth' % n
    if n % 10 == 1: return u'%sst' % n
    if n % 10 == 2: return u'%snd' % n
    if n % 10 == 3: return u'%srd' % n
    return u'%sth' % n

JavaScript

function ordinal(n) {
    if (10 < n && n < 14) return n + 'th';
    switch (n % 10) {
        case 1: return n + 'st';
        case 2: return n + 'nd';
        case 3: return n + 'rd';
        default: return n + 'th';
    }
}

By special-casing 11, 12, and 13, the function becomes incredibly simple.

I'm pleased to have found a context in which JavaScript's switch statement is almost elegant. The problem, usually, is the need to break to prevent fall-through. When used within a function, though, the return statement is able to perform this role, making the JavaScript code almost as readable as the Python equivalent.

Comments

David:

Thanks for this. It's definitely simple and elegant. Much better than any other ordinal method I've seen. The only suggestion I would make is to allow for negative numbers. Personally, I can't think of a good use case, but I don't like that it's a limitation of the function.

It's a very easy mod … just get the absolute value of the number (which we'll test against), then return the original number + ordinal value:

Number.prototype.ordinal = function() {
    var n = Math.abs(this);
    if (10 < n && n < 14) return this + 'th';
    switch (n % 10) {
        case 1: return this + 'st';
        case 2: return this + 'nd';
        case 3: return this + 'rd';
        default: return this + 'th';
    }
};
Rob O

Thanks, Rob. I've never encountered a negative ordinal number, but it's good to see that they're easily handled.

Also, I edited your comment (on Disqus) to preserve the formatting of your code snippet. (This site accepts Markdown in comments, something I really ought to make clear.)

Respond