1

I am trying to display a date and time using vanilla Javascript. I want to show the full date and time with the user's timezone.

Here is my desired output:

Wednesday, January 30th 2019 at 08:48:47 AM PST

And here's what I have so far:

var date = new Date();
var n = date.toDateString();
var time = date.toLocaleTimeString();

document.getElementById('time').innerHTML = n + ' at ' + time;
<div id="time"></div>

So I'm pretty close. All I need now is to expand the day and month name to the full name, add st/rd/th to the day and append the user's timezone to the end of it all.

user13286
  • 3,027
  • 9
  • 45
  • 100
  • Possible duplicate of [JavaScript new Date Ordinal (st, nd, rd, th)](https://stackoverflow.com/questions/15397372/javascript-new-date-ordinal-st-nd-rd-th) – Get Off My Lawn Jan 30 '19 at 17:30

3 Answers3

2

This solution uses Intl.DateTimeFormat() so that we can utilize the FormatToParts() function then apply a custom map() then finally reduce() to get the desired output.

Within the map() function we append the day suffixes to output 'st', 'nd', 'rd', and 'th'. E.g. 1st, 2nd, 3rd, 4th. The suffix is appended to the day itself, as opposed to the corresponding literal key, because we need to know the value of the day so this was the easiest route to take.

Where we do replace the value of the literal it is mostly to remove extra commas (there by default) and to also to display at before the the time.

References at MDN:

const d = new Date();

const formatOptions = {
    weekday: 'long', month: 'long', day: 'numeric', hour: 'numeric',
    minute: 'numeric', year: 'numeric', timeZoneName: 'short', hour12: true
};

// Using Intl.DateTimeFormat so we have access to
//     formatToParts function which produces
//     an Array of objects containing the formatted date in parts
const dateFormat = new Intl.DateTimeFormat(undefined, formatOptions);

// Keep track of 'literal' key counts (`literal` is the separator)
let separatorIndex = 0;

// Where the magic happens using map() and reduce()
const dateString = dateFormat.formatToParts(d).map(({type, value}) => {
  switch (type) {
    case 'literal' :
      separatorIndex++;
      
      switch (separatorIndex) {
        case 3 : // Day separator
          return ' ';
          break;
        case 4 : // Year separator
          return ' at ';
        default: return value;          
      }
      break;
    case 'day' :
      // Append appropriate suffix
      switch (value) {
        case (value.slice(-1) === 1) :
          return value.concat('st');
          break;
        case (value.slice(-1) === 2) :
          return value.concat('nd');
          break;
        case (value.slice(-1) === 3) :
          return value.concat('rd');
          break;
        default: return value.concat('th');
      }
      break;
    case 'hour' :
      // Prepend 0 when less than 10 o'clock
      return (value < 10) ? '0'.concat(value) : value;
      break;
    default: return value;
  }
}).reduce((string, part) => {
  return string.concat(part)
});

// Not part of answer; only for output result
document.write(dateString);
seantunwin
  • 1,698
  • 15
  • 15
1

Vanilla JS - no problem! Internationalization API to the rescue! (From MDN)

var date = new Date(), 
    locale = 'en-US',
    timeZone = 'America/Los_Angeles';

var weekday = new Intl.DateTimeFormat(locale, { weekday: 'long', timeZone }).format(date);
var month = new Intl.DateTimeFormat(locale, { month: 'long', timeZone }).format(date);
var day = new Intl.DateTimeFormat(locale, { day: '2-digit', timeZone }).format(date);

var time = new Intl.DateTimeFormat(locale, 
{
  hour: '2-digit', 
  minute: '2-digit', 
  second: '2-digit',
  hour12: true,
  timeZone

}).format(date);

console.log(`${weekday}, ${month} ${day}th ${date.getFullYear()} at ${time}`);
Matt Morgan
  • 4,900
  • 4
  • 21
  • 30
ymz
  • 6,602
  • 1
  • 20
  • 39
  • 1
    `timezone` should be `timeZone`, and I'd recommend leaving `locale` as `undefined`. Not everyone lives in the US ;) – Patrick Roberts Jan 30 '19 at 19:07
  • This still is not _quite_ the OP's desired format: `Wednesday, January 30th 2019 at 08:48:47 AM PST` – Matt Morgan Jan 30 '19 at 19:27
  • 1
    Wow, had no idea this existed. Really cool! I was able to get the Timezone name using `Intl.DateTimeFormat().resolvedOptions().timeZone` it's not quite in the format I want(ie it says `America/Chicago` instead of `CST`), but I will accept this answer and keep looking into it. – user13286 Jan 30 '19 at 19:41
1
var date = new Date();
var n = date.toDateString();
var time = date.toLocaleTimeString();
var hours = date.getHours();
var AP = hours >= 12 ? 'PM' : 'AM';

var day = date.getDay();
var weekday = "";
if(day === 0)weekday = "Monday"; else if(day === 1) weekday = "Tuesday" ; 
else if(day === 2) weekday = "Wednesday";  else if(day === 3) weekday = "Thursday";
else if(day === 4) weekday = "Friday"; else if(day === 5) weekday = "Saturday";
else if(day === 6) weekday = "Sunday";

var monthNo = date.getMonth();
var month = "";
if(monthNo === 0)month = "January";
else if(monthNo === 1)month = "February";
else if(monthNo === 2)month = "March";
else if(monthNo === 3)month = "April";
else if(monthNo === 4)month = "May";
else if(monthNo === 5)month = "June";
else if(monthNo === 6)month = "July";
else if(monthNo === 7)month = "August";
else if(monthNo === 8)month = "September";
else if(monthNo === 9)month = "October";
else if(monthNo === 10)month = "November";
else if(monthNo === 11)month = "December";

var dateNo = date.getDate();
var dateletter = "";

if (dateNo > 3 && dateNo < 21) dateletter =  "th"; 
else if(dateNo % 10 === 1) dateletter =  "st"; 
else if(dateNo % 10 === 2) dateletter =  "nd"; 
else if(dateNo % 10 === 3) dateletter =  "rd"; 
else dateletter = "th";


console.log(weekday +", " + month + " " + dateNo + dateletter + " at " + time + " " + 
" " +AP);`

To add the time zone to this you can use the javascript gettimeoffset() method to get the time zone offset. according to that you can decide the time zone.