API
@-Formulas
JavaScript
LotusScript
Reg Exp
Web Design
Notes Client
XPages
 
Format Date
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 (MM/DD/YYYY, DD/MM/YYYY, MM-DD-YYYY, 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. This week I'll talk about the function to format the date and next week I'll talk about the function to format the time.

function formatDate(dateValue, format) {

The variable dateValue is a JavaScript date/time value. The variable format is a string. The string holds the format. There are two allowed separators between months, days, and years - they are the dash (aka hyphen) and the slash. Between the separators are the months, days, and years. If you want to force a leading zero for the month, then you should include MM for the month value. A single M for the month value will drop the leading zero. It works the same way for days - you can include either DD or D for the days. The year value is always four digits, so YYYY needs to be used.

For example, the following are valid format strings:
MM/DD/YYYY This will be a two digit month, then a slash, then a two digit day, then a slash, then a four digit year.
DD-MM-YYYY This will be a two digit day, then a dash, then a two digit month, then a dash, then a four digit year.
YYYY/M/D This will be a four digit year, then a slash, then the month without a leading zero, then a slash, then a day without a leading zero.

The following are not valid format strings:
MM/DD-YYYY This is not valid because the separator needs to be the same in both positions.
MM~DD~YYYY This is not valid because the tilde is not a valid separator.
MM/DD/YY This is not valid because the year has to be 4 digits.

Any invalid format is converted to MM/DD/YYYY (the US format). 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 = /^(M|MM|D|DD|YYYY)([\-\/]{1})(M|MM|D|DD|YYYY)(\2)(M|MM|D|DD|YYYY)$/;
    if (!re.test(fmt)) { fmt = "MM/DD/YYYY"; }
    if (fmt.indexOf("M") == -1) { fmt = "MM/DD/YYYY"; }
    if (fmt.indexOf("D") == -1) { fmt = "MM/DD/YYYY"; }
    if (fmt.indexOf("YYYY") == -1) { fmt = "MM/DD/YYYY"; }

I use a regular expression to do the first part of the validation, then make sure that all three pieces (month, day, and year) are included. This is because a format string of MM/MM/MM would pass the validation but is not a valid format string.

The next thing the code does is get one and two digit months, one and two digit days, and a four digit year:

    var M = "" + (dateValue.getMonth()+1);
    var MM = "0" + M;
    MM = MM.substring(MM.length-2, MM.length);
    var D = "" + (dateValue.getDate());
    var DD = "0" + D;
    DD = DD.substring(DD.length-2, DD.length);
    var YYYY = "" + (dateValue.getFullYear());

To get the single digit and two digit values, I first create the "without leading zero" value. Let's look at the month as an example. I want it to be a string, so I force the empty string at the start and then append the month value. So the variable M has a value of "0" through "12". Then I put a leading zero on the front to get MM. That leading zero is fine for "01" through "09", but it isn't right for "010" through "012". So the second statement takes the last two characters.

The next thing to do is figure out what separator was used and split up the format string into three pieces based on the separator.

    var sep = "/";
    if (fmt.indexOf("-") != -1) { sep = "-"; }
    var pieces = fmt.split(sep);
    var result = "";

Finally, the variable result is built with the three pieces. Each piece needs to be looked at independently and the correct variable added to the result string. For example, here is the first part of the result:

    switch (pieces[0]) {
         case "M" : result += M + sep; break;
         case "MM" : result += MM + sep; break;
         case "D" : result += D + sep; break;
         case "DD" : result += DD + sep; break;
         case "YYYY" : result += YYYY + sep; break;
    }

If the first piece is the month without a leading zero, then the variable M and the separator are added to the result string. The second and third pieces of the result string are added in a similar fashion:

    switch (pieces[1]) {
         case "M" : result += M + sep; break;
         case "MM" : result += MM + sep; break;
         case "D" : result += D + sep; break;
         case "DD" : result += DD + sep; break;
         case "YYYY" : result += YYYY + sep; break;
    }
    switch (pieces[2]) {
         case "M" : result += M; break;
         case "MM" : result += MM; break;
         case "D" : result += D; break;
         case "DD" : result += DD; break;
         case "YYYY" : result += YYYY; break;
    }

When the full result string is built, that is returned as the value of the function:

    return result;
}


So, this function should be able to give you the text representation of a date value in the desired format. Like I said earlier, this code can be modified to include other separators, or change the default format, or include the possibility of a two digit year.