Is there a JavaScript code snippet to take a value of 1-31 and convert it to 1st, 2nd, 3rd, etc?
Thanks!
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
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:
%
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
). undefined
value, which is falsey.The logic exploits these facts to return the correct suffix from a compact expression with these parts.
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
.
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.
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.
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
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