Javascript: convert 24-hour time-of-day string to 12-hour time with AM/PM and no timezone

150,943

Solution 1

Nothing built in, my solution would be as follows :

function tConvert (time) {
  // Check correct time format and split into components
  time = time.toString ().match (/^([01]\d|2[0-3])(:)([0-5]\d)(:[0-5]\d)?$/) || [time];

  if (time.length > 1) { // If time format correct
    time = time.slice (1);  // Remove full string match value
    time[5] = +time[0] < 12 ? 'AM' : 'PM'; // Set AM/PM
    time[0] = +time[0] % 12 || 12; // Adjust hours
  }
  return time.join (''); // return adjusted time or original string
}

tConvert ('18:00:00');

This function uses a regular expression to validate the time string and to split it into its component parts. Note also that the seconds in the time may optionally be omitted. If a valid time was presented, it is adjusted by adding the AM/PM indication and adjusting the hours.

The return value is the adjusted time if a valid time was presented or the original string.

Working example

(function() {

  function tConvert(time) {
    // Check correct time format and split into components
    time = time.toString().match(/^([01]\d|2[0-3])(:)([0-5]\d)(:[0-5]\d)?$/) || [time];

    if (time.length > 1) { // If time format correct
      time = time.slice(1); // Remove full string match value
      time[5] = +time[0] < 12 ? 'AM' : 'PM'; // Set AM/PM
      time[0] = +time[0] % 12 || 12; // Adjust hours
    }
    return time.join(''); // return adjusted time or original string
  }

  var tel = document.getElementById('tests');

  tel.innerHTML = tel.innerHTML.split(/\r*\n|\n\r*|\r/).map(function(v) {
    return v ? v + ' => "' + tConvert(v.trim()) + '"' : v;
  }).join('\n');
})();
<h3>tConvert tests : </h3>
<pre id="tests">
  18:00:00
  18:00
  00:00
  11:59:01
  12:00:00
  13:01:57
  24:00
  sdfsdf
  12:61:54
</pre>

Solution 2

toLocaleTimeString() makes this very simple. There is no need to do this yourself anymore. You'll be happier and live longer if you don't try to attack dates with string methods. (They will fight back.)

const timeString = '18:00:00'
// Prepend any date. Use your birthday.
const timeString12hr = new Date('1970-01-01T' + timeString + 'Z')
  .toLocaleTimeString('en-US',
    {timeZone:'UTC',hour12:true,hour:'numeric',minute:'numeric'}
  );
document.getElementById('myTime').innerText = timeString12hr
<h1 id='myTime'></h1>

Solution 3

To get AM/PM, Check if the hour portion is less than 12, then it is AM, else PM.

To get the hour, do (hour % 12) || 12.

This should do it:

var timeString = "18:00:00";
var H = +timeString.substr(0, 2);
var h = H % 12 || 12;
var ampm = (H < 12 || H === 24) ? "AM" : "PM";
timeString = h + timeString.substr(2, 3) + ampm;

http://jsfiddle.net/Skwt7/4/

That assumes that AM times are formatted as, eg, 08:00:00. If they are formatted without the leading zero, you would have to test the position of the first colon:

var hourEnd = timeString.indexOf(":");
var H = +timeString.substr(0, hourEnd);
var h = H % 12 || 12;
var ampm = (H < 12 || H === 24) ? "AM" : "PM";
timeString = h + timeString.substr(hourEnd, 3) + ampm;

http://jsfiddle.net/Skwt7/3/

Solution 4

Based on gilly3's answer.

If you want to convert:

 08:00 to 08:00 AM 
 16:00 to 04:00 PM

Then this will work:

function tConv24(time24) {
  var ts = time24;
  var H = +ts.substr(0, 2);
  var h = (H % 12) || 12;
  h = (h < 10)?("0"+h):h;  // leading 0 at the left for 1 digit hours
  var ampm = H < 12 ? " AM" : " PM";
  ts = h + ts.substr(2, 3) + ampm;
  return ts;
};

https://jsfiddle.net/fpjs9g0L/

Solution 5

Short ES6 code

const convertFrom24To12Format = (time24) => {
  const [sHours, minutes] = time24.match(/([0-9]{1,2}):([0-9]{2})/).slice(1);
  const period = +sHours < 12 ? 'AM' : 'PM';
  const hours = +sHours % 12 || 12;

  return `${hours}:${minutes} ${period}`;
}
const convertFrom12To24Format = (time12) => {
  const [sHours, minutes, period] = time12.match(/([0-9]{1,2}):([0-9]{2}) (AM|PM)/).slice(1);
  const PM = period === 'PM';
  const hours = (+sHours % 12) + (PM ? 12 : 0);

  return `${('0' + hours).slice(-2)}:${minutes}`;
}
Share:
150,943
Tim
Author by

Tim

Updated on July 08, 2022

Comments

  • Tim
    Tim almost 2 years

    The server is sending a string in this format: 18:00:00. This is a time-of-day value independent of any date. How to convert it to 6:00PM in Javascript? I could prepend today's date as a string to the value sent by the server and then parse the combined values and then try the .toTimeString() method of the Date object, but the format that time method emits is 24-hour time with a seconds chunk. I could write a function, but is there something built in?

  • Tim
    Tim over 11 years
    thanks for the answer "nothing built in" and for the function using regex.
  • Tim
    Tim over 11 years
    thanks for the function using substr. Since HBP's solution removes the seconds chunk, I'm giving him the green check even though your answer was the first in. Besides, he's only at 3K; you're rolling in points with 21K :-)
  • gilly3
    gilly3 over 11 years
    Ah. Somehow I didn't notice that you wanted to remove the seconds.
  • skhurams
    skhurams about 11 years
    @HBP when there is no date only time is in string the only way you can covert 24 hour format to 12 hour format is only your code worked for me bundle of thanks
  • iamsaksham
    iamsaksham almost 8 years
    what if its 12:30 PM
  • gilly3
    gilly3 almost 8 years
    @isaksham - 12:30 PM expressed as HH:MM:SS is 12:30:00. If you use var timeString = "12:30:00" in my code above, you will get output of "12:30PM", as expected. I worked with a group of Russians once who were baffled by the American way of using AM and PM. It made no sense to them to transition from 11:59 AM to 12:00 PM. The explanation is that PM means "after mid-day", and noon is mid-day.
  • sanjeev shetty
    sanjeev shetty over 7 years
    I think, we need a space in time[5] = +time[0] < 12 ? 'AM' : 'PM'; // Set AM/PM to time[5] = +time[0] < 12 ? ' AM' : ' PM'; // Set AM/PM for further usage any calculations or something else
  • Vadim
    Vadim almost 6 years
    Bug: 00:08:00 is converted to 00:08 am instead of 12:08 am.
  • Sachin HR
    Sachin HR almost 6 years
    But it works only for PM.For AM it is not appending AM to the time
  • Frédéric Camblor
    Frédéric Camblor almost 6 years
    Down voted : timeTo12HrFormat("00:00:00") gives "0:00:00 AM" instead of "12:00:00 AM"
  • HBP
    HBP almost 5 years
    I would argue that time minutes and seconds fields are always double digits. If you REALLY need single digit seconds change the RegExp by adding a ? between the ']' and '\d' of the seconds.
  • Saroj Shrestha
    Saroj Shrestha almost 5 years
    @HBP how to remove those seconds part. Need to show just HH:MM AM and want to show double digits for hour instead of one something link 5:30 -> 05:30
  • Saroj Shrestha
    Saroj Shrestha almost 5 years
    @gilly3 how to display two digit hour instead of one like 06:30 instead of 6:30
  • gilly3
    gilly3 almost 5 years
    @SarojShrestha - You can use padStart(). If your site supports IE, be sure to include the polyfill.
  • Tim
    Tim over 4 years
    +1. I do wish to be happier and live longer! What, specifically, causes the seconds chunk to be suppressed upon output? Is it because the seconds property has been left undefined?
  • bbsimonbb
    bbsimonbb over 4 years
    Yup. If you don't specify anything, everything comes out. Once you start specifying, you only get what you ask for. Happy long life !
  • Samiksha Jagtap
    Samiksha Jagtap almost 4 years
    this is great way
  • huykon225
    huykon225 almost 3 years
    I am using this code but in my country it's not showing AM/PM. It will show CH replace. How to fix this?
  • bbsimonbb
    bbsimonbb over 2 years
    The first argument to toLocaleTimeString is the culture. It used to be empty, but I've updated the answer now to 'en-US' because the question specifically asks for AM/PM. This obviously defeats localization but should fix your problem. What's your country ? What do you see if you run navigator.language ?
  • bbsimonbb
    bbsimonbb over 2 years
    Something got built in. Since 2016 or so, there's no need to do this yourself.