One thing in JavaScript that's really lacking is date formatting. If you want to display a date in JavaScript there aren't a whole lot of options available especially if you want to display a date as numeric notation (ie. 10/31/2007 for example). I decided that I need at least some basic date formatting functionality in my apps, so I created a basic date formatting function. While I was at it I had to create a few helpers along the way which I'll also show below.

This is one thing where the Microsoft ASP.NET AJAX client library actually excels - it has a whole complement of type formatting functions similar to .NET code, but since I'm not using the library I needed to roll my own. I took a brief look to see what the MS client libs are doing but the amount of code involved for formatting is huge and scattered all over the place. To be expected though given in the completeness of the support which is much more than my simple needs. (FWIW, it's really interesting to see the sheer amount of code that runs in the MS AJAX libraries!).

I also searched around for a other JavaScript implementations and I dug up a few but the problem with many of them is that the code gets rather lengthy quickly as most libraries  support too many features including string based date representations, which then requires localization etc.

My main goal is to provide only basic date formatting for numeric date display. Things like 12/01/1966 and 2005-12-31 19:00:31 and 12-07 or 12:01pm for example. That's only a fraction of the date formatting we're used to in .NET, but really how many different date formats do you ever work with anyway?

In any case here's a formatDate extension for the Date prototype:

Date.prototype.formatDate = function(format)
{
    var date = this;
    if (!format)
      format="MM/dd/yyyy";               
 
    var month = date.getMonth() + 1;
    var year = date.getFullYear();    
 
    format = format.replace("MM",month.toString().padL(2,"0"));        
 
    if (format.indexOf("yyyy") > -1)
        format = format.replace("yyyy",year.toString());
    else if (format.indexOf("yy") > -1)
        format = format.replace("yy",year.toString().substr(2,2));
 
    format = format.replace("dd",date.getDate().toString().padL(2,"0"));
 
    var hours = date.getHours();       
    if (format.indexOf("t") > -1)
    {
       if (hours > 11)
        format = format.replace("t","pm")
       else
        format = format.replace("t","am")
    }
    if (format.indexOf("HH") > -1)
        format = format.replace("HH",hours.toString().padL(2,"0"));
    if (format.indexOf("hh") > -1) {
        if (hours > 12) hours - 12;
        if (hours == 0) hours = 12;
        format = format.replace("hh",hours.toString().padL(2,"0"));        
    }
    if (format.indexOf("mm") > -1)
       format = format.replace("mm",date.getMinutes().toString().padL(2,"0"));
    if (format.indexOf("ss") > -1)
       format = format.replace("ss",date.getSeconds().toString().padL(2,"0"));
    return format;
}

With this you can format dates like this:

var date = new Date();
var cr = "\n";
var str = date.formatDate("yyyy-MM-dd HH:mm") + cr +
          date.formatDate("MM/dd/yyyy hh:mm t") + cr +
          date.formatDate("MM-yyyy hh:mmt") ;
alert(str);  

The date formatting isn't terribly flexible so months, days, hours, minutes and seconds can only be represented in 2 digit format, but again that's the most common way to do it anyway around the world.

The code above depends on a few helper functions that String.prototype.padL and String.prototype.padR and String.repeat:

String.repeat = function(chr,count)
{    
    var str = ""; 
    for(var x=0;x<count;x++) {str += chr}; 
    return str;
}
String.prototype.padL = function(width,pad)
{
    if (!width ||width<1)
        return this;   
 
    if (!pad) pad=" ";        
    var length = width - this.length
    if (length < 1) return this.substr(0,width);
 
    return (String.repeat(pad,length) + this).substr(0,width);    
}    
String.prototype.padR = function(width,pad)
{
    if (!width || width<1)
        return this;        
 
    if (!pad) pad=" ";
    var length = width - this.length
    if (length < 1) this.substr(0,width);
 
    return (this + String.repeat(pad,length)).substr(0,width);
} 

The static String.repeat repeats a given character or string n number of times, which is required for padding values. .padL and padR, pad a string left and right and also trim a string if the width is exceeded. This is useful in many situations for string trimming and in the date formatting for right filling numbers with 0's (ie. 2 turns into 02).

While I was at it I also ran into a very basic string.format implemementation which was just too easy to pass up. Again, not a full implementation like in .NET in that it only supports string replacement without format specifiers, but still highly useful:

String.format = function(frmt,args)
{   
    for(var x=0; x<arguments.length; x++)
    {
        frmt = frmt.replace("{" + x + "}",arguments[x+1]);
    }
    return frmt;
}

With it you can turn the previous data example to:

var date = new Date();
var cr = "\n";    
alert(String.format("Date 1: {0}\nDate 2:{1}\nDate3: {2}",                
            date.formatDate("yyyy-MM-dd HH:mm"),
            date.formatDate("MM/dd/yyyy hh:mm t"),
            date.formatDate("MM-yyyy hh:mmt") )
    );

Even this very basic implementation can save a fair bit of string concatenation code in many cases.

None of this is rocket science of course, but it's nice to have a few small and lean functions that provide basic utility functionality to your JavaScript code. Basic date formatting especially is something I've often cursed and this will go a long way to simplifying matters.