Rick Strahl's Weblog  

Wind, waves, code and everything in between...
.NET • C# • Markdown • WPF • All Things Web
Contact   •   Articles   •   Products   •   Support   •   Advertise
Sponsored by:
West Wind WebSurge - Rest Client and Http Load Testing for Windows

A simple formatDate function for JavaScript


:P
On this page:

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.

Posted in JavaScript  wwHoverPanel  

The Voices of Reason


 

David Betz
March 18, 2008

# re: A simple formatDate function for JavaScript

I actually like to use DateJS (http://www.datejs.com/) for all my date/time manipulation and access. It's amazingly powerful.

Rick Strahl
March 18, 2008

# re: A simple formatDate function for JavaScript

Yeah I looked at this library and it's extremely complete, but also rather large. I needed something I can include self-contained as part of my internal library.

Tom Groeger
March 18, 2008

# re: A simple formatDate function for JavaScript

Very nice code, Rick, thanks a lot for sharing it. With Ajax all around a good collection of Javascript classes and libraries becomes more and more important, and I like it lean and mean. Especially the string.format function is so easy and yet so useful, I could clap my head that I didn't think of it earlier ... probably too obvious<g>
Tom

Kevin Pirkl
March 20, 2008

# re: A simple formatDate function for JavaScript

Not a small JS lib (normal 12781bytes minified 4247bytes) but a good one - http://www.svendtofte.com/code/date_format/

Andrew R
March 20, 2008

# re: A simple formatDate function for JavaScript

Gees, is it really that hard to find a better way of putting the same formatters in work? For instance, the one probably mentioned in the comments above employs regexp's 'replace(str, replacementFunction)'. That's coolest of all time in my opinion.
Then, repeat(chr,count), best implementation (optimized for speed) is as such: { var parts = new Array(count+1); parts.join(chr); }. Won't everybody agree? This you can find in the prototype.js library, and shame on me I forgot the name of the person who introduced it.
Summing, before introducing some code from a tribune such as you, Rick, have, and introducing it as a allegedly good example to follow, make sure your code is real good. I'm sorry for my negative comment here. But someone needs to have said that a long time ago. This goes only, strictly, to your JavaScript examples. Best wishes, anyhow.

Rick Strahl
March 21, 2008

# re: A simple formatDate function for JavaScript

Hi Andrew - while I'll agree that perhaps my JavaScript skills are only mediocre <g>, I do take issue with posting sub-optimal code. Sure we all want to post the best code possible but there are always 50 different ways to approach the issue. And I actually do it frequently here to play off quick code I have knocked out but that can possibly be improved or can benefit from discussions. This is a blog not a magazine or online article, so I frequently kick out stuff that I've just worked on and hasn't necessarily been through an extensive test of time or review.

One thing I've found here on the blog is that comments very often come up with solutions that are better than what I originally posted and while sometimes it can be embarrassing (to me) I still think that that's a great thing overall. Often times there are also new feature ideas or completely overlooked aspects.

The value of posts like this IMHO is to give ideas or point out things we do frequently and repeatedly without much thought. And as I mentioned above a lot of times more complete solutions come out of the comments and frequently there's the value of the post and not necessarily directly in the code but the topic and discussion as a whole.

That said - while I get the idea of what you're saying, why don't you post the code of a revision alternative which you already have in your head and contribute it here? That'll really make your point and also provide a public contribution that will be useful for others...

Samir Nigam
September 23, 2008

# re: A simple formatDate function for JavaScript

Hi,

Let current time be 7:21 PM

then

var date = new Date();
alert(String.format("{0}", date.formatDate("MM/dd/yyyy hh:mm:ss t")));

displays 09/23/2008 19:21:31 pm instead of 09/23/2008 07:21:31

Is it a bug or somthing else?

Rick Strahl
September 23, 2008

# re: A simple formatDate function for JavaScript

Use uppercase HH instead of hh to use 24 hour clock. Remove the t which shows the am/pm designation.

var date = new Date();
alert(String.format("{0}", date.formatDate("MM/dd/yyyy HH:mm:ss")));

Ran Davidovitz
January 09, 2009

# re: A simple formatDate function for JavaScript

Great post, personally i generally tend to use a more "framework" (completed) solution (E.g. DateJS, extendDate, etc), but i agree that for a specific use this is ok.
The basic requirement that i think every developer need to take in mind is not to hard code the layout! e.g. for Hebrew its dd/mm/yy and for English its mm/dd/yy.

Tommy Lenz
January 23, 2009

# re: A simple formatDate function for JavaScript

No so much a bug as a typo.
The line: if (hours > 12) hours - 12;
should be: if (hours > 12) hours -= 12;

This will fix the issue first mentioned by Samir Nigam.

do from candida diet
February 18, 2009

# re: A simple formatDate function for JavaScript

I search up and down for a function that can format date easily based on any format in javascript and found your post. It's great, now I have the solution for my web application. I needed to do validate and display in a correct date format. Thanks

Rodd
March 17, 2009

# re: A simple formatDate function for JavaScript

Hey Rick,

I like it, nice and concise.

However, is there anything that can be done to get it to work with the culture of the browser? IOW, if I set my default browser culture to de-DE or to en-AU and enter 14/8/1969 into the following textbox:
<asp:TextBox id="test" runat="server" onblur="this.value= new Date(this.value).formatDate('MM-yyyy');"/>

I would expect to see 08-1969 but instead I see 02-1970.

Thanks.

Rick Strahl
March 17, 2009

# re: A simple formatDate function for JavaScript

Yes this compact function doesn't deal with localized date formats because that gets fairly complicated and will require significantly more logic then this entire function set. I think I mentioned that the behavior is minimal and specific to a single locale.

Russell J. Stoner
April 29, 2009

# re: A simple formatDate function for JavaScript

Hi, Rick. I am a "long-time listener, first-time caller." ;)

I was looking for an ultra-lightweight JavaScript function to format dates and was happy to come across your post. After using it for a bit, I found myself wanting the following: 1) to mimic more of Microsoft's custom date and time format strings function (http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx), and 2) handling JSON dates with Microsoft's formatting.

For the first item, I made the the following changes (still relatively compact, in my opinion):
Date.prototype.formatDate = function(format) {
    var date = this;
    var _monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
    var _dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
    var _year = date.getFullYear();
    var _month = date.getMonth();
    var _day = date.getDay();
    var _date = date.getDate();
    var _hours = date.getHours();
    var _minutes = date.getMinutes();
    var _seconds = date.getSeconds();

    if (!format)
        format = "MM/dd/yyyy";

    format = format.replace("yyyy", "{0}").replace("yy", "{1}").replace("y", "{2}")
            .replace("MMMM", "{3}").replace("MMM", "{4}").replace("MM", "{5}").replace("M", "{6}")
            .replace("dddd", "{7}").replace("ddd", "{8}").replace("dd", "{9}").replace("d", "{10}")
            .replace("hh", "{11}").replace("h", "{12}").replace("HH", "{13}").replace("H", "{14}")
            .replace("mm", "{15}").replace("m", "{16}")
            .replace("ss", "{17}").replace("s", "{18}")
            .replace("tt", "{19}").replace("t", "{20}");

    if (format.indexOf("{0}") > -1)
        format = format.replace("{0}", _year.toString());
    if (format.indexOf("{1}") > -1)
        format = format.replace("{1}", _year.toString().substr(2, 2));
    if (format.indexOf("{2}") > -1)
        format = format.replace("{2}", parseInt(_year.toString().substr(2, 2)).toString());

    if (format.indexOf("{3}") > -1)
        format = format.replace("{3}", _monthNames[_month]);
    if (format.indexOf("{4}") > -1)
        format = format.replace("{4}", _monthNames[_month].substr(0, 3));
    if (format.indexOf("{5}") > -1)
        format = format.replace("{5}", (_month + 1).toString().padL(2, "0"));
    if (format.indexOf("{6}") > -1)
        format = format.replace("{6}", (_month + 1).toString());

    if (format.indexOf("{7}") > -1)
        format = format.replace("{7}", _dayNames[_day]);
    if (format.indexOf("{8}") > -1)
        format = format.replace("{8}", _dayNames[_day].substr(0, 3));
    if (format.indexOf("{9}") > -1)
        format = format.replace("{9}", _date.toString().padL(2, "0"));
    if (format.indexOf("{10}") > -1)
        format = format.replace("{10}", _date.toString());

    if (format.indexOf("{11}") > -1) {
        var _h = _hours;
        if (_hours > 12) _h -= 12;
        if (_hours == 0) _h = 12;
        format = format.replace("{11}", _h.toString().padL(2, "0"));
    }
    if (format.indexOf("{12}") > -1) {
        var _h = _hours;
        if (_hours > 12) _h -= 12;
        if (_hours == 0) _h = 12;
        format = format.replace("{12}", _h.toString());
    }
    if (format.indexOf("{13}") > -1)
        format = format.replace("{13}", _hours.toString().padL(2, "0"));
    if (format.indexOf("{14}") > -1)
        format = format.replace("{14}", _hours.toString());

    if (format.indexOf("{15}") > -1)
        format = format.replace("{15}", _minutes.toString().padL(2, "0"));
    if (format.indexOf("{16}") > -1)
        format = format.replace("{16}", _minutes.toString());

    if (format.indexOf("{17}") > -1)
        format = format.replace("{17}", _seconds.toString().padL(2, "0"));
    if (format.indexOf("{18}") > -1)
        format = format.replace("{18}", _seconds.toString());

    if (format.indexOf("{19}") > -1) {
        if (_hours > 11)
            format = format.replace("{19}", "pm")
        else
            format = format.replace("{19}", "am");
    }
    if (format.indexOf("{20}") > -1) {
        if (_hours > 11)
            format = format.replace("{20}", "p")
        else
            format = format.replace("{20}", "a");
    }

    return format;
}


For the second part, I added the following small block of code:
String.prototype.jsonFormatDate = function(format) {
    var t = parseInt(this.replace(/\/Date\(/, "").replace(/\)\//, ""));
    var d = new Date();
    d.setTime(t);
    return d.formatDate(format);
}

Russell J. Stoner
April 30, 2009

# re: A simple formatDate function for JavaScript

Actually, the following is a better approach to handling JSON dates with Microsoft's formatting than what I had previously posted:

String.prototype.formatDate = function(format) {
    var d = new Date();
    if (this.indexOf("/Date(") == 0) {
        d.setTime(parseInt(this.replace(/\/Date\(/, "").replace(/\)\//, "")));
    } else {
        d = new Date(this);
    }
    return d.formatDate(format);
}


This approach can "detect" the Microsoft formatting; otherwise, it leaves the string alone. Additionally, the prototype function name for the String (formatDate) is now the same as for Date. This makes things more consistent.

Dan
May 31, 2010

# re: A simple formatDate function for JavaScript

So, for the second time today, I've discovered the answer on your site after looking on Google for 20 minutes!

however... After you mentioned the great libraries for .Net, I realized.... hey, javascript for dates really sucks. So... I wrote a quick handler in about 20 seconds to use "isDate" and then send back the format I like. I called that handler via Ajax from the page. :)

JavaScript gurus world wide would be horrified. But... a flawless solution that's just a bit over-the-top.

Rick Strahl
June 01, 2010

# re: A simple formatDate function for JavaScript

@Dan - an Ajax call for date conversion is a bit overkill :-). However, I think it's safe to say that using ViewModels on the server that pre-format dates there would be the ideal solution for date display and avoid having to do client side date conversion.

Lauri Lubi
June 11, 2010

# re: A simple formatDate function for JavaScript

Shouldn't it be: if (hours > 12) hours -= 12;
instead of: if (hours > 12) hours - 12;

jaXXXon
November 27, 2010

# re: A simple formatDate function for JavaScript

This library is the best thing I have come across for date formatting in JavaScript:

http://fisforformat.sourceforge.net/

It is able to output every date format I can think of (and then some) and it has some other neat features!


(FYI, it was listed as a jQuery plugin, but I've confirmed it works perfectly fine without jQuery.)

Clarence Fredericks
February 07, 2011

# re: A simple formatDate function for JavaScript

I came across a brand new JavaScript library called jPaq which provides a function that closely emulates PHP's date function. Documentation for this function can be found here: http://jpaq.org/documentation/Date.prototype.format%28%29/1.0/.

West Wind  © Rick Strahl, West Wind Technologies, 2005 - 2024