JavaScript new Date Ordinal (st, nd, rd, th)

Solution 1:

Note this works for day numbers from 1 to 31.

const nth = function(d) {
  if (d > 3 && d < 21) return 'th';
  switch (d % 10) {
    case 1:  return "st";
    case 2:  return "nd";
    case 3:  return "rd";
    default: return "th";
  }
}

// test code

const fortnightAway = new Date(+new Date + 12096e5);
const date = fortnightAway.getDate();
const month = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"][fortnightAway.getMonth()];

document.getElementById("date").innerHTML = `In two weeks it will be the ${date}<sup>${nth(date)}</sup> of ${month} ${fortnightAway.getFullYear()}`;

// test
const dates = [...Array(32).keys()].slice(1).map(i => `${i}${nth(i)}`)
console.log(dates.join(", "))
sup {
  font-size: x-small
}
<span id="date"></span>

Here is a version for any number

const nth = function(d) {
  const dString = String(d);
  const last = +dString.slice(-2);
  if (last > 3 && last < 21) return 'th';
  switch (last % 10) {
    case 1:  return "st";
    case 2:  return "nd";
    case 3:  return "rd";
    default: return "th";
  }
}

// test
const numbers = [...Array(1225).keys()].map(i => `${i}${nth(i)}`)
console.log(numbers.join(", "))
sup {
  font-size: x-small
}
<span id="date"></span>

Solution 2:

Here is a one liner inspired by the other answers. It is tested and will take 0 and negative numbers.

function getOrdinalNum(n) {
  return n + (n > 0 ? ['th', 'st', 'nd', 'rd'][(n > 3 && n < 21) || n % 10 > 3 ? 0 : n % 10] : '');
}

Update 2020-06-23. The following is a better readable answer of the function above:

const getOrdinalNum = (number) => {
  let selector;

  if (number <= 0) {
    selector = 4;
  } else if ((number > 3 && number < 21) || number % 10 > 3) {
    selector = 0;
  } else {
    selector = number % 10;
  }

  return number + ['th', 'st', 'nd', 'rd', ''][selector];
};


Solution 3:

I was doing this for dates as well, but because the day of month can only be between 1 and 31, I ended up with a simplified solution.

function dateOrdinal(dom) {
    if (dom == 31 || dom == 21 || dom == 1) return dom + "st";
    else if (dom == 22 || dom == 2) return dom + "nd";
    else if (dom == 23 || dom == 3) return dom + "rd";
    else return dom + "th";
};

or compact version using conditional operators

function dateOrdinal(d) {
    return d+(31==d||21==d||1==d?"st":22==d||2==d?"nd":23==d||3==d?"rd":"th")
};

http://jsben.ch/#/DrBpl