JavaScript new Date Ordinal (st, nd, rd, th)
Asked Answered
O

23

98

If at all possible, without JavaScript libraries or lots of clunky code I am looking for the simplest way to format a date two weeks from now in the following format:

13th March 2013

The code I am using is:

var newdate = new Date(+new Date + 12096e5);
document.body.innerHTML = newdate;

which returns the date and time two weeks from now, but like this: Wed Mar 27 2013 21:50:29 GMT+0000 (GMT Standard Time)

Here is the code in jsFiddle.

Any help would be appreciated!

Olla answered 13/3, 2013 at 22:2 Comment(4)
apart from a missing "of" I have no problem with that dateMidget
try this #1057228Rambort
I was wondering how to do exactly the opposite ? I don't want to bring up new thread so if someone has the link I'd appreciate itSialagogue
This is outside of the scope of the original question, but I don't suppose anyone has tackled ordinals in other languages? I know French does theirs a bit different, for example.Gilgai
M
155

Note this works for day numbers from 1 to 31.

const nth = (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 = (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(", "))

Oneliner suggested in comments

const nth = n => n>3&&n<21?"th":n%10==1?"st":n%10==2?"nd":n%10==3?"rd":"th";

// to call: nth(i)

// test
document.getElementById("nums").innerHTML =  [...Array(1225).keys()].map(i => `<pre>${String(i).padStart(3," ")}<sup>${nth(i)}</sup></pre>`).join(" ");
pre { display:inline-block; margin:2px; }
<div id="nums"></div>

If you do not like switch, this will work equally well

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

// test
const numbers = [...Array(1225).keys()].map(i => `${i}${nth(i)}`)
console.log(numbers.join(", "))
Midget answered 13/3, 2013 at 22:11 Comment(5)
Works perfect... +1 for d>3 && d<21Meador
For clarity, I'd probably code the exceptions as either: if (n == 11 || n == 12 || n == 13) return "th"; or: if (n >= 11 && n <= 13) return "th";Brunobruns
That is missing 21,22,23Midget
Ordinal function (compressed): function nth(n){return n>3&&n<21?"th":n%10==2?"nd":n%10==2?"nd":n%10==3?"rd":"th"}Jaquelinejaquelyn
Minor typo in the above function, this should work: function nth(n){return n>3&&n<21?"th":n%10==1?"st":n%10==2?"nd":n%10==3?"rd":"th"}Promotive
L
37

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];
};


Lotson answered 7/6, 2017 at 17:0 Comment(1)
This won't work for 111, 112, 113, 211, etc. This might work for all. ["th", "st", "nd", "rd"][n % 100 > 10 && n % 100 < 14) || n % 10 > 3 ? 0 : n % 10] but there's no such case for dates. In case someone needs to use it for any positive integerBlackcap
B
11

If you are a fan of moment.js, then you can make it with format("Do")

Examples

var newdate = new Date();
moment(newdate).format("Do MMMM YYYY")
//Returns 1st January 2020

moment("01/01/2020", "MM/DD/YYYY").format("Do")
//Returns 1st

moment("01/01/2020", "MM/DD/YYYY").format("Do MMM YYYY")
//Returns 1st Jan 2020
Banker answered 21/4, 2020 at 12:17 Comment(0)
R
10

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

Renaldorenard answered 15/2, 2017 at 22:57 Comment(0)
Z
8

There are a lot of good answers here already, although one that makes use of Intl.PluralRules, which standardises the classification of ordinals across locales, may still be useful.

Below are some implementations for en-GB.

jsfiddle

  • a one liner:

    console.log({one:'st',two:'nd',few:'rd',other:'th'}[new Intl.PluralRules('en-GB', { type: 'ordinal' }).select(new Date().getDate())])
    
  • a verbose example:

    const suffixMap = {
      one: 'st',
      two: 'nd',
      few: 'rd',
      other: 'th',
    };
    const locale = 'en-GB';
    const moment = new Date();
    const dayOfMonth = moment.getDate();
    const pluralRuleOptions = {
      type: 'ordinal',
    };
    const pluralRule = new Intl.PluralRules(locale, pluralRuleOptions);
    const ordinal = pluralRule.select(dayOfMonth);
    console.log(suffixMap[ordinal])
    

const suffix = {
  one: 'st',
  two: 'nd',
  few: 'rd',
  other: 'th',
};

document.getElementById("tomorrow-month").innerHTML = new Intl.DateTimeFormat('en-GB', { month: 'long' }).format(new Date(Date.now() + 86400000));
document.getElementById("tomorrow-day").innerHTML = new Intl.DateTimeFormat('en-GB', { day: 'numeric' }).format(new Date(Date.now() + 86400000));
document.getElementById("tomorrow-ordinal").innerHTML = suffix[new Intl.PluralRules('en-GB', { type: 'ordinal' }).select(new Date(Date.now() + 86400000).getDate())];

document.getElementById("yesterday-month").innerHTML = new Intl.DateTimeFormat('en-GB', { month: 'long' }).format(new Date(Date.now() - 86400000));
document.getElementById("yesterday-day").innerHTML = new Intl.DateTimeFormat('en-GB', { day: 'numeric' }).format(new Date(Date.now() - 86400000));
document.getElementById("yesterday-ordinal").innerHTML = suffix[new Intl.PluralRules('en-GB', { type: 'ordinal' }).select(new Date(Date.now() - 86400000).getDate())];
Tomorrow, on <span id="tomorrow-month"></span> <span id="tomorrow-day"></span><sup id="tomorrow-ordinal"></sup>, I ordered a time machine.
It arrived yesterday on <span id="yesterday-month"></span> <span id="yesterday-day"></span><sup id="yesterday-ordinal"></sup>.
Zygophyllaceous answered 23/10, 2021 at 11:0 Comment(2)
Is there any best practice for a suffix map that would support multiple languages?Homogeny
I found this https://mcmap.net/q/218635/-javascript-ordinal-suffix-locale-translation/329062 which suggests building a table for all dates instead of trying to calculate the ordinal.Homogeny
R
6

Here's a simple function that works with any number:

function getOrdinal(n) {
    let ord = ["st", "nd", "rd"]
    let exceptions = [11, 12, 13]
    let nth = 
    ord[(n % 10) - 1] == undefined || exceptions.includes(n % 100) ? "th" : ord[(n % 10) - 1]
    return n + nth
}

It can accept a number or number as a string. For example:

getOrdinal(28)        //Outputs: 28th
getOrdinal('108')     //Outputs: 108th
Resemble answered 20/1, 2021 at 8:2 Comment(0)
B
5

One more solution in the sea of solutions.

let suffix = (day >= 4 &&  day <= 20) || (day >= 24 && day <= 30)
    ? "th"
    : ["st", "nd", "rd"][day % 10 - 1];
Bashemeth answered 22/6, 2020 at 8:51 Comment(1)
+1 for brevity and clarity, thank you! I read all the reasonably short ones and this one resonated on both counts.Paxwax
C
4

Lots of formatting answers, so I'll just work on the nth of any integer-

Number.prototype.nth= function(){
    if(this%1) return this;
    var s= this%100;
    if(s>3 && s<21) return this+'th';
    switch(s%10){
        case 1: return this+'st';
        case 2: return this+'nd';
        case 3: return this+'rd';
        default: return this+'th';
    }
}
Cybele answered 13/3, 2013 at 22:14 Comment(2)
The if is for teens, so 13 is 13th and not 13rd.Cybele
Why the this%1? Mod 1 is always 0 so the statement will always fail, no?Eisenhower
H
4

If you are a fan of dayjs, which is now preferred over moment, here is an example:

you can just do dayjs(date).format('Do') but I've included an example to show how you can use it with any format you want.

Note that date ordinality is available with Dayjs advanced formats.

var advancedFormat = require('dayjs/plugin/advancedFormat')
dayjs.extend(advancedFormat)

// date variable - your date to format eg:- 2022-04-01T21:27:00
dayjs(date).format('dddd, MMMM Do [at] h:mma')

Output for above example (2022-04-01T21:27:00):

enter image description here

Huonghupeh answered 2/4, 2022 at 3:50 Comment(0)
I
2

Lots of answers, here's another:

function addOrd(n) {
  var ords = [, 'st', 'nd', 'rd'];
  var ord, m = n % 100;
  return n + ((m > 10 && m < 14) ? 'th' : ords[m % 10] || 'th');
}

// Return date string two weeks from now (14 days) in 
// format 13th March 2013
function formatDatePlusTwoWeeks(d) {
  var months = ['January', 'February', 'March', 'April', 'May', 'June',
    'July', 'August', 'September', 'October', 'November', 'December'
  ];

  // Copy date object so don't modify original
  var e = new Date(d);

  // Add two weeks (14 days)
  e.setDate(e.getDate() + 14);
  return addOrd(e.getDate()) + ' ' + months[e.getMonth()] + ' ' + e.getFullYear();
}

console.log(formatDatePlusTwoWeeks(new Date()));

// Alternative using Intl.DateTimeFormat
function datePlusTwoWeeks(date = new Date()) {
  let d = new Date(date.getFullYear(), date.getMonth(), date.getDate() + 14);
  let parts = new Intl.DateTimeFormat('en',{
    year: 'numeric',
    month: 'long',
    day: 'numeric'
  }).formatToParts(d).reduce((acc, part) => {
    acc[part.type] = part.value;
    return acc;
  }, Object.create(null));
  return `${addOrd(parts.day)} ${parts.month} ${parts.year}`;
}

console.log(datePlusTwoWeeks())
Incoming answered 13/3, 2013 at 22:28 Comment(0)
O
2

This works great for me

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

usage:

console.log(ordinal(11))
OUTPUT: 11th
Oculo answered 20/10, 2021 at 13:43 Comment(0)
B
2

Here is a modern approach using the Intl library:

const locale = 'en-US',
      suffixMap = { one: 'st', two: 'nd', few: 'rd', other: 'th' },
      pluralRule = new Intl.PluralRules(locale, { type: 'ordinal', }),
      withOrdinal = (n) => `${n}${suffixMap[pluralRule.select(n)]}`,
      dateFmt = Intl.DateTimeFormat(locale, { month: 'long', year: 'numeric' }),
      formatDate = (date) => `${withOrdinal(date.getDate())} ${dateFmt.format(date)}`;

console.log(formatDate(new Date()));

Here is another approach.

const locale = 'en-US',
      suffixMap = { one: 'st', two: 'nd', few: 'rd', other: 'th' },
      pluralRule = new Intl.PluralRules(locale, { type: 'ordinal', }),
      withOrdinal = (n) => `${n}${suffixMap[pluralRule.select(n)]}`,
      dayOfWeekFormatter = Intl.DateTimeFormat(locale, { weekday: 'long' }),
      monthFormatter = Intl.DateTimeFormat(locale, { month: 'long' });

const getDayInfo = () => {
  const now = new Date(),
        dayOfWeek = now.getDay(),
        currentMonth = now.getMonth(),
        currDate = new Date(now.getTime());
  let occurance = 1;
  
  while (currDate.getMonth() > currentMonth - 1) {
    currDate.setDate(currDate.getDate() - 1);
    if (currDate.getDay() === dayOfWeek) {
      occurance++;
    }
  }
    
  const ordinal = withOrdinal(occurance),
        weekday = dayOfWeekFormatter.format(now),
        month = monthFormatter.format(now);
  
  return `Today is the ${ordinal} ${weekday} of ${month}`;
};

const info = getDayInfo();

console.log(info);
Brass answered 19/6, 2023 at 17:38 Comment(0)
G
1

I'm a bit late to the party, but this should work:

function ordinal(number) {
  number = Number(number)
  if(!number || (Math.round(number) !== number)) {
    return number
  }
  var signal = (number < 20) ? number : Number(('' + number).slice(-1))
  switch(signal) {
    case 1:
      return number + 'st'
    case 2:
      return number + 'nd'
    case 3:
      return number + 'rd'
    default:
      return number + 'th'
  }
}

function specialFormat(date) {
  // add two weeks
  date = new Date(+date + 12096e5)
  var months = [
    'January'
    , 'February'
    , 'March'
    , 'April'
    , 'May'
    , 'June'
    , 'July'
    , 'August'
    , 'September'
    , 'October'
    , 'November'
    , 'December'
  ]
  var formatted = ordinal(date.getDate())
  formatted += ' ' + months[date.getMonth()]
  return formatted + ' ' + date.getFullYear()
}

document.body.innerHTML = specialFormat(new Date())
Garver answered 8/8, 2013 at 18:15 Comment(0)
H
0

As many has mentioned, here is another answer.

This is directly based on @kennebec's answer, which I found the most simplest way to get this date Ordinal generated for given JavaScript date:

I created two prototype function as follows:

Date.prototype.getDateWithDateOrdinal = function() {
    var d = this.getDate();  // from here on I've used Kennebec's answer, but improved it.
    if(d>3 && d<21) return d+'th';
    switch (d % 10) {
        case 1:  return d+"st";
        case 2:  return d+"nd";
        case 3:  return d+"rd";
        default: return d+"th";
    }
};

Date.prototype.getMonthName = function(shorten) {
    var monthsNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    var monthIndex = this.getMonth();
    var tempIndex = -1;
    if (monthIndex == 0){ tempIndex = 0 };
    if (monthIndex == 1){ tempIndex = 1 };
    if (monthIndex == 2){ tempIndex = 2 };
    if (monthIndex == 3){ tempIndex = 3 };
    if (monthIndex == 4){ tempIndex = 4 };
    if (monthIndex == 5){ tempIndex = 5 };
    if (monthIndex == 6){ tempIndex = 6 };
    if (monthIndex == 7){ tempIndex = 7 };
    if (monthIndex == 8){ tempIndex = 8 };
    if (monthIndex == 9){ tempIndex = 9 };
    if (monthIndex == 10){ tempIndex = 10 };
    if (monthIndex == 11){ tempIndex = 11 };

    if (tempIndex > -1) {
        this.monthName = (shorten) ? monthsNames[tempIndex].substring(0, 3) : monthsNames[tempIndex];
    } else {
        this.monthName = "";
    }

    return this.monthName;
};

Note: just include the above prototype functions within your JS Script and use it as described bellow.

And whenever there is a JS date I need to generate the date with date ordinal I use that prototype method as follows on that JS date:

var myDate = new Date();
// You may have to check your JS Console in the web browser to see the following
console.log("date with date ordinal: "+myDate.getDateWithDateOrdinal()+" "+myDate.getMonthName()+" "+myDate.getFullYear());

// or I will update the Div. using jQuery
$('#date').html("date with date ordinal: "+myDate.getDateWithDateOrdinal()+" "+myDate.getMonthName()+" "+myDate.getFullYear());

And it will print out date with date ordinal as shown in the following live demo:

	Date.prototype.getMonthName = function(shorten) {
		var monthsNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
		var monthIndex = this.getMonth();
		var tempIndex = -1;
	    if (monthIndex == 0){ tempIndex = 0 };
	    if (monthIndex == 1){ tempIndex = 1 };
	    if (monthIndex == 2){ tempIndex = 2 };
	    if (monthIndex == 3){ tempIndex = 3 };
	    if (monthIndex == 4){ tempIndex = 4 };
	    if (monthIndex == 5){ tempIndex = 5 };
	    if (monthIndex == 6){ tempIndex = 6 };
	    if (monthIndex == 7){ tempIndex = 7 };
	    if (monthIndex == 8){ tempIndex = 8 };
	    if (monthIndex == 9){ tempIndex = 9 };
	    if (monthIndex == 10){ tempIndex = 10 };
	    if (monthIndex == 11){ tempIndex = 11 };

	    if (tempIndex > -1) {
			this.monthName = (shorten) ? monthsNames[tempIndex].substring(0, 3) : monthsNames[tempIndex];
	    } else {
	    	this.monthName = "";
	    }

	    return this.monthName;
	};

    Date.prototype.getDateWithDateOrdinal = function() {
		var d = this.getDate();  // from here on I've used Kennebec's answer, but improved it.
	    if(d>3 && d<21) return d+'th';
	    switch (d % 10) {
            case 1:  return d+"st";
            case 2:  return d+"nd";
            case 3:  return d+"rd";
            default: return d+"th";
        }
	};

	var myDate = new Date();
    // You may have to check your JS Console in the web browser to see the following
	console.log("date with date ordinal: "+myDate.getDateWithDateOrdinal()+" "+myDate.getMonthName()+" "+myDate.getFullYear());
    
    // or I will update the Div. using jQuery
    $('#date').html("date with date ordinal: "+myDate.getDateWithDateOrdinal()+" "+myDate.getMonthName()+" "+myDate.getFullYear());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="date"></p>

.

Hosanna answered 14/10, 2015 at 19:49 Comment(0)
P
0

A short and compact solution:

function format(date, tmp){
  return [
    (tmp = date.getDate()) + 
      ([, 'st', 'nd', 'rd'][/1?.$/.exec(tmp)] || 'th'),
    [ 'January', 'February', 'March', 'April',
      'May', 'June', 'July', 'August',
      'September', 'October', 'November', 'December'
    ][date.getMonth()],
    date.getFullYear()
  ].join(' ')
}


// 14 days from today

console.log('14 days from today: ' + 
  format(new Date(+new Date + 14 * 864e5)));

// test formatting for all dates within a month from today

var day = 864e5, today = +new Date;
for(var i = 0; i < 32; i++) {
  console.log('Today + ' + i + ': ' + format(new Date(today + i * day)))
}

(The compact regex-based approach for getting the ordinal suffix appears several places around the web, original source unknown)

Parthenopaeus answered 14/5, 2017 at 19:33 Comment(0)
C
0

	Date.prototype.getMonthName = function(shorten) {
		var monthsNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
		var monthIndex = this.getMonth();
		var tempIndex = -1;
	    if (monthIndex == 0){ tempIndex = 0 };
	    if (monthIndex == 1){ tempIndex = 1 };
	    if (monthIndex == 2){ tempIndex = 2 };
	    if (monthIndex == 3){ tempIndex = 3 };
	    if (monthIndex == 4){ tempIndex = 4 };
	    if (monthIndex == 5){ tempIndex = 5 };
	    if (monthIndex == 6){ tempIndex = 6 };
	    if (monthIndex == 7){ tempIndex = 7 };
	    if (monthIndex == 8){ tempIndex = 8 };
	    if (monthIndex == 9){ tempIndex = 9 };
	    if (monthIndex == 10){ tempIndex = 10 };
	    if (monthIndex == 11){ tempIndex = 11 };

	    if (tempIndex > -1) {
			this.monthName = (shorten) ? monthsNames[tempIndex].substring(0, 3) : monthsNames[tempIndex];
	    } else {
	    	this.monthName = "";
	    }

	    return this.monthName;
	};

    Date.prototype.getDateWithDateOrdinal = function() {
		var d = this.getDate();  // from here on I've used Kennebec's answer, but improved it.
	    if(d>3 && d<21) return d+'th';
	    switch (d % 10) {
            case 1:  return d+"st";
            case 2:  return d+"nd";
            case 3:  return d+"rd";
            default: return d+"th";
        }
	};

	var myDate = new Date();
    // You may have to check your JS Console in the web browser to see the following
	console.log("date with date ordinal: "+myDate.getDateWithDateOrdinal()+" "+myDate.getMonthName()+" "+myDate.getFullYear());
    
    // or I will update the Div. using jQuery
    $('#date').html("date with date ordinal: "+myDate.getDateWithDateOrdinal()+" "+myDate.getMonthName()+" "+myDate.getFullYear());
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<p id="date"></p>
Consol answered 14/4, 2018 at 19:12 Comment(1)
1. Why no comments. 2. Why hide the code? 3. You can remove the tempindex and just have var monthIndex = this.getMonth(); return (shorten) ? monthsNames[monthIndex].substring(0, 3) : monthsNames[monthIndex];Midget
I
0
function getSuffixForDate(day) {
  const lastNumberOfTheDay = day[day.length];

  const suffixes = {
    1: () => 'st',
    21: () => 'st',
    31: () => 'st',
    2: () => 'nd',
    22: () => 'nd',
    3: () => 'rd',
    23: () => 'rd',
  };

  return suffixes[lastNumberOfTheDay] !== undefined ? `${day}${suffixes[lastNumberOfTheDay]()}` : `${day}th`;
}

const date = new Date();
const formattedDate = `${getSuffixForDate(date.getDate())} ${monthNames[date.getMonth()]} ${date.getFullYear()}`;

A human readable version...

Incite answered 28/6, 2019 at 8:56 Comment(1)
It's just a lot simpler solution. It will check the last number in day and then check if it exists in the object. If it does then return the correct suffix and then if not return th.Incite
T
0

Here's a readable, ES+ kinda version.

const getDateSuffix = (date) => {
  const thExpections = date => [11, 12, 13].some(exception => exception === date);
  const lastDigit = date % 10;

  if (thExpections(date) || lastDigit === 0 || lastDigit > 3) return `${date}th`;
  if (lastDigit === 1) return `${date}st`;
  if (lastDigit === 2) return `${date}nd`;
  return `${date}rd`;
};

const monthNames = [
  "January",
  "February",
  "March",
  "April",
  "May",
  "June",
  "July",
  "August",
  "September",
  "October",
  "November",
  "December",
];

const twoWeeksFromNow = new Date(+new Date + 12096e5);
console.log(`Two weeks from now: ${getDateSuffix(twoWeeksFromNow.getDate())} ${monthNames[twoWeeksFromNow.getMonth()]} ${twoWeeksFromNow.getFullYear()}`)

console.log(`
=================
Test date suffixes:`);
const logOutDates = new Array(31).fill(0).forEach((_, index) => console.log(getDateSuffix(index + 1)))
Transportation answered 14/3, 2021 at 13:8 Comment(0)
C
0

without JavaScript libraries or lots of clunky code

One simple approach to achieve this is in vanilla javascript would be to use a series of three ternary statements to determine the ordinal, like this:

let dateOrdinal = 'th';

dateOrdinal = ([1, 21, 31].indexOf(dateNumber) > -1) ? 'st' : dateOrdinal;
dateOrdinal = ([2, 22].indexOf(dateNumber) > -1) ? 'nd' : dateOrdinal;
dateOrdinal = ([3, 23].indexOf(dateNumber) > -1) ? 'rd' : dateOrdinal;

It's not quite as human-readable, but you could also use a switch/case statement to make the same determination:

switch (true) {
  
  case ([1, 21, 31].indexOf(dateNumber) > -1) : let dateOrdinal = 'st'; break;
  case ([2, 22].indexOf(dateNumber) > -1) : let dateOrdinal = 'nd'; break;
  case ([3, 23].indexOf(dateNumber) > -1) : let dateOrdinal = 'rd'; break;
  default : let dateOrdinal = 'th';
}

Working Example:

// GET DATE PARTS
const dateInTwoWeeks = new Date(+new Date + 12096e5);
const dateNumber = dateInTwoWeeks.getDate();
const dateMonth = dateInTwoWeeks.toLocaleString('default', {month: 'long'});
const dateYear = dateInTwoWeeks.getFullYear();

// DETERMINE DATE ORDINAL
let dateOrdinal = 'th';

dateOrdinal = ([1, 21, 31].indexOf(dateNumber) > -1) ? 'st' : dateOrdinal;
dateOrdinal = ([2, 22].indexOf(dateNumber) > -1) ? 'nd' : dateOrdinal;
dateOrdinal = ([3, 23].indexOf(dateNumber) > -1) ? 'rd' : dateOrdinal;

// FORMAT DATE AS STRING
const dateInTwoWeeksString = `${dateNumber}${dateOrdinal} ${dateMonth} ${dateYear}`; 

document.body.textContent = dateInTwoWeeksString;
Culinarian answered 14/12, 2021 at 0:29 Comment(3)
I really, really dislike switch(true)Midget
Go on then, @mplungjan. I'd be intrigued to hear why. I tend to prefer switch / case rather than endless else if () {} else if () {} else if () {} and I am so pleased when I can actually deploy switch / case without using switch(true). All too often, I find that switch(true) is unavoidable in order to deploy switch / case in the first place.Culinarian
I find it an abuse of a side effect. Please scroll up to my accepted answer for a much more readable version which is using switch as it is supposed to be usedMidget
P
0

I think this is pretty cool way to get the date suffix

      getDateSuffix(datePart: number): string {
        const stAr = [1, 21, 31];
        const ndAr = [2, 22];
        const rdAr = [3, 23];
    
        const suffixesRaw = [
          { suffix: 'st', numbers: stAr },
          { suffix: 'nd', numbers: ndAr },
          { suffix: 'rd', numbers: rdAr },
        ];
    
        const suffixes = suffixesRaw
          .filter(x => x.numbers.filter(y => y == datePart).length > 0)
          .map(z => z.suffix);
    
        return suffixes.length > 0 ? suffixes[0] : 'th';
      }
Prae answered 16/4, 2022 at 1:18 Comment(0)
U
-1

Super simple functional implementation:

const ordinal = (d) => {
  const nth = { '1': 'st', '2': 'nd', '3': 'rd' }
  return `${d}${nth[d] || 'th'}`
}

const monthNames = ['January','February','March','April','May','June','July','August','September','October','November','December']

const dateString = (date) => `${ordinal(date.getDate())} ${monthNames[date.getMonth()]} ${date.getFullYear()}`

// Use like this: 
dateString(new Date()) // 18th July 2016
Unsphere answered 19/7, 2016 at 3:50 Comment(1)
Unfortunately this method is too simple and doesn't work for days like the 21st.Instruction
P
-1

Strongly inspired by @user2309185's.

const ordinal = (d) => {
  return d + (['st', 'nd', 'rd'][d % 10 - 1] || 'th')
}
Petaloid answered 26/1, 2017 at 11:26 Comment(1)
I found an issue with this, 13 = 13rdModla
O
-1

Here is an easy solution:

var date = today.getDate() + (today.getDate() % 10 == 1 && today.getDate() != 11 ? + 'st': (today.getDate() % 10 == 2 && today.getDate() != 12 ? + 'nd': 

(today.getDate() % 10 == 3 && today.getDate() != 13 ? + 'rd':'th')));
Oregon answered 7/1, 2018 at 6:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.