Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Take a value 1-31 and convert it to ordinal date w/ JavaScript

Is there a JavaScript code snippet to take a value of 1-31 and convert it to 1st, 2nd, 3rd, etc?

Thanks!

like image 414
Reg Avatar asked Sep 19 '12 01:09

Reg


2 Answers

You might find it convenient to monkey-patch the function into the Number prototype, so you can call it as a method on the number (implementation shamelessly stolen from Pradeep's answer):

Number.prototype.toOrdinal = function() {
  var n = this.valueOf(),
      s = [ 'th', 'st', 'nd', 'rd' ],
      v = n % 100;
  return n + (s[(v-20)%10] || s[v] || s[0])
}

Example use:

var someDay = Math.floor(Math.random() * 31 + 1);
alert(someDay.toOrdinal())

Or you may believe that Monkey Patching Is Evil; as usual, YMMV.

(I sometimes call this particular method th, but that works somewhat better in languages where you don't need the parentheses for invocation.)

Adding an explanation of the logic. Key points that are Javascript-specific:

  1. The % operator returns negative results for a negative dividend modulo a positive divisor (so -1 % 5 is -1; many other implementations of the modulus operator return only answers between 0 and n-1, so -1 % 5 is 4).
  2. Attempting to index an array by a value outside the valid range of indexes (either negative or past the end of the array) results in the undefined value, which is falsey.

The logic exploits these facts to return the correct suffix from a compact expression with these parts.

  1. Try to access s[(v-20)%10]. If v (which is the given number modulo 100) is less than 20, then the index is negative and the array access returns undefined. Otherwise, the array index is between 0 and 9. Values 0 through 3 return the correct associated suffix ("th", "st", "nd", and "rd"), while anything greater than 3 will again return undefined.

  2. If the result of 1 is a defined value, return it; otherwise, try to access s[v]. If v is itself 0, 1, 2, or 3, we again get "th", "st", "nd", or "rd" respectively. Otherwise, we get an undefined value, and the expression moves on to the next alternative.

  3. If neither of the above results is defined, we return s[0], which is "th".

The result is that everything from 4 through 20 - including 11, 12, and 13 - gets a "th", while all other numbers ending in 1, 2, or 3 get "st", "nd", and "rd", respectively.

like image 91
Mark Reed Avatar answered Oct 06 '22 00:10

Mark Reed


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

Thanks @RobG bit modified version

function getOrdinal(n) {
    if((parseFloat(n) == parseInt(n)) && !isNaN(n)){
        var s=["th","st","nd","rd"],
        v=n%100;
        return n+(s[(v-20)%10]||s[v]||s[0]);
    }
    return n;     
}

Tests

getOrdinal("test");   // test
getOrdinal(1.5);      // 1.5
getOrdinal(1);        // 1st
getOrdinal(2);        // 2nd
getOrdinal(3);        // 3rd
getOrdinal(4);        // 4th
getOrdinal(true);     // true
getOrdinal(Infinity); // Infinity
getOrdinal(NaN);      // NaN
getOrdinal(void 0);   // undefined
like image 29
Pradeep Sanjaya Avatar answered Oct 06 '22 01:10

Pradeep Sanjaya