Reg Exp
Web Design
Notes Client
Format Time
A few weeks ago I had a need to format a date and a time on a web page. There were all kinds of users, so I wanted to be able to let the user pick their format (HH:MM:SS, HH:MM, H:MM:SS, etc) to show the date value and time value. I ended up writing two functions - one for the date and one for the time - that take in a JavaScript date/time value and a format string, and return the date (or time) in the desired format. Last week I talked about the function to format the date and this week I talk about the function to format the time.

function formatTime(timeValue, format) {

The variable timeValue is a JavaScript date/time value. The variable format is a string. The string holds the format. The format has the hour with a leading zero ("HH") or without ("H") followed by a colon then the two digit minutes ("MM"). If you want to include the seconds (optional) then you have another colon followed by the two digit seconds ("SS"). If you want to include the meridian (AM or PM) - again, optional - then you have a space and "AM". If the meridian is not included, the hours will be on the 24-hour clock. The meridian is always in upper case.

For example, the following are valid format strings:
H:MM:SS This will output the hours, minutes, and seconds in 24-hour format without a leading zero for the hours.
H:MM:SS AM This will output the hours, minutes, and seconds and either "AM" or "PM" without a leading zero for the hours.
HH:MM AM This will output the hours and minutes (no seconds) and either "AM" or "PM" with a leading zero for the hours.

The following are not valid format strings:
H:M:SS This is not valid because the minutes value must always contain two digits.
HH:MM:SS PM This is not valid because the meridian (AM/PM) must always be "AM".
HH+MM AM This is not valid because the separator must be a colon.

Any invalid format is converted to H:MM AM. Obviously, you can change the code if you want to make the default be another format or allow for additional formats.

The first part of the code validates the format:

    var fmt = format.toUpperCase();
    var re = /^(H|HH)(:MM)(:SS)?( AM)?$/;
    if (!re.test(fmt)) { fmt = "H:MM AM"; }

I use a regular expression to validate the format. The first part can be either a single H or a double HH. Then the colon and minutes must appear. Then the colon and seconds are optional (the "?" means the previous group should appear 0 or 1 time). Then the meridian is optional.

The next thing the code does is get one and two digit hours, two digit minutes, and two digits seconds:

    var MM = "0" + (timeValue.getMinutes());
    MM = MM.substring(MM.length-2, MM.length);
    var SS = "0" + (timeValue.getSeconds());
    SS = SS.substring(SS.length-2, SS.length);
    var H = "" + (timeValue.getHours());
    var HH = "0" + H;
    HH = HH.substring(HH.length-2, HH.length);

To get the two digit values, let's look at the minutes as an example. I want it to be a string, so I force the leading zero as a string at the start and then append the minute value. So the variable MM has a value of "00" through "09" and "010" through "059". The second statement takes the last two characters, which preserves the leading zero for those numbers less than 10 and removes the leading zero for the numbers 10 and greater.

The code then computes the meridian value if that is in the format string:

    var meridian = "";
    if (fmt.indexOf(" AM") != -1) {
         meridian = "AM";
         if (HH == "00") { HH = "12"; }
         if (HH == "12") { meridian = "PM"; }
         if (parseInt(HH, 10) > 12) {
              meridian = "PM";
              var hrs = (parseInt(HH, 10)-12);
              H = "" + hrs;
              HH = "0" + H;
              HH = HH.substring(HH.length-2, HH.length);

The standard JavaScript function getHours() that was used to get the hours returns a number from 0 to 23 (military time). So if the hours, with the leading zero, is "00", then that is converted to 12:00 AM. If the hours is "12", then the hours don't need to change but the meridian is "PM". If the hours are 13 or higher, then 12 hours are subtracted and the meridian is "PM". Hours between 1:00 AM and 11:00 AM are not converted (the assumed meridian of "AM" happens at the start of the block).

The time string is then build based on the format and returned:

    var meridian = "";
    var result = "";
    if (fmt.indexOf("HH") == -1) { result += H + ":" + MM; } else { result += HH + ":" + MM; }
    if (fmt.indexOf("SS") != -1) { result += ":" + SS; }
    if (fmt.indexOf(" AM") != -1) { result += " " + meridian; }
    return result;