Reg
Reg

Reputation: 161

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!

Upvotes: 12

Views: 3849

Answers (4)

mikemaccana
mikemaccana

Reputation: 123228

npm install ordinal

Works in both the browser and node. Then just:

var ordinal = require('ordinal')

ordinal(1);   //=> '1st'
ordinal(2);   //=> '2nd'
ordinal(3);   //=> '3rd'
ordinal(4);   //=> '4th'

ordinal(11);  //=> '11th'
ordinal(12);  //=> '12th'
ordinal(13);  //=> '13th'

ordinal(21);  //=> '21st'
ordinal(22);  //=> '22nd'
ordinal(23);  //=> '23rd'
ordinal(24);  //=> '24th'

https://www.npmjs.com/package/ordinal

Upvotes: 0

Pradeep Sanjaya
Pradeep Sanjaya

Reputation: 1846

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

Upvotes: 22

Mark Reed
Mark Reed

Reputation: 95252

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.

Upvotes: 3

RobG
RobG

Reputation: 147413

Pradeep's answer is cool, but something a bit more robust should test the value and do something sensible if it's not a suitable value for adding an ordinal (like just return the value), e.g.

var getOrdinal = (function() {

    var re = /^\d+$/;
    var ordinal = ["th","st","nd","rd"];

    return function (value) {

      var t;

      if (re.test(String(value))) {
        t = value % 100;
        return t + (ordinal[(t - 20 % 10)] || ordinal[t] || 'th');            
      }

      return value;
    }
}());

getOrdinal( void 0 );  // undefined
getOrdinal(        );  // undefined
getOrdinal( NaN    );  // NaN
getOrdinal( true   );  // true
getOrdinal( 1.0    );  // 1st
getOrdinal( ''     );  // '' (empty string)
getOrdinal(Infinity);  // Infinity

Upvotes: 1

Related Questions