Sometimes you write code that you wish you could totally rework. That is how I feel about jPaq’s Date.prototype.format(). The real issue I have with it is that the metacharacters are not intuitive. Therefore, I decided to write a new version of this function which is more intuitive. The following is the definition:


// Date.prototype.format() - By Chris West - MIT Licensed
(function() {
  var D = "Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday".split(","),
      M = "January,February,March,April,May,June,July,August,September,October,November,December".split(",");
  Date.prototype.format = function(format) {
    var me = this;
    return format.replace(/a|A|Z|S(SS)?|ss?|mm?|HH?|hh?|D{1,4}|M{1,4}|YY(YY)?|'([^']|'')*'/g, function(str) {
      var c1 = str.charAt(0),
          ret = str.charAt(0) == "'"
          ? (c1=0) || str.slice(1, -1).replace(/''/g, "'")
          : str == "a"
            ? (me.getHours() < 12 ? "am" : "pm")
            : str == "A"
              ? (me.getHours() < 12 ? "AM" : "PM")
              : str == "Z"
                ? (("+" + -me.getTimezoneOffset() / 60).replace(/^\D?(\D)/, "$1").replace(/^(.)(.)$/, "$10$2") + "00")
                : c1 == "S"
                  ? me.getMilliseconds()
                  : c1 == "s"
                    ? me.getSeconds()
                    : c1 == "H"
                      ? me.getHours()
                      : c1 == "h"
                        ? (me.getHours() % 12) || 12
                        : (c1 == "D" && str.length > 2)
                          ? D[me.getDay()].slice(0, str.length > 3 ? 9 : 3)
                          : c1 == "D"
                            ? me.getDate()
                            : (c1 == "M" && str.length > 2)
                              ? M[me.getMonth()].slice(0, str.length > 3 ? 9 : 3)
                              : c1 == "m"
                                ? me.getMinutes()
                                : c1 == "M"
                                  ? me.getMonth() + 1
                                  : ("" + me.getFullYear()).slice(-str.length);
      return c1 && str.length < 4 && ("" + ret).length < str.length
        ? ("00" + ret).slice(-str.length)
        : ret;
    });
  };
})();

Description

Creates a string from the date using the specified format string. The following table can be used to get the desired results:

Format Output Meaning
YYYY 2012 Four-digit representation of the year.
YY 12 Two-digit representation of the year.
MMMM September Full textual representation of the month.
MMM Sep Three letter representation of the month.
MM 09 Month with the leading zero (two digits long).
M 9 Month without the leading zero.
DDDD Wednesday Full textual representation of the day of the week.
DDD Wed Three letter representation of the day of the week.
DD 03 Day of the month with leading zero (two digits long).
D 3 Day of the month without leading zeros.
HH 19 24-hour format of hour with leading zero (two digits long).
hh 07 12-hour format of hour with leading zero (two digits long).
H 19 24-hour format of hour without leading zeros.
h 7 12-hour format of hour without leading zeros.
mm 01 Minutes with the leading zero (two digits long).
m 1 Minutes without the leading zero.
ss 08 Seconds with the leading zero (two digits long).
s 8 Seconds without the leading zero.
a pm Lowercase am or pm.
A PM Uppercase AM or PM.
SSS 095 Milliseconds with leading zeros (three digits long).
S 95 Milliseconds without leading zeros.
Z -0400 Difference to Greenwich time (GMT) in hours.
'NO ''FORMAT'' HERE' NO 'FORMAT' HERE The specified string within the single quotes printed literally. To escape a single quote, you must prepend it with another single quote.
Date Used:  Wednesday September 3, 2012 19:01:08.095 GMT-0400 (EDT)

Parameters

  1. format
    The string that will be used to format the date.  Any of the formats shown in the previous table are acceptable.

Returns

The date formatted as specified by the format parameter.

Examples

Now let’s look at an example of calling this function to get what you want.


var format = "'It is now' h:mm:ss.SSS A 'on' DDDD, MMMM D, YYYY.";
alert((new Date).format(format));

JS Bin

Personally, I like this a lot better than the current version of the Date.prototype.format(). Let me know if you think it can be improved in some way.


4 Comments

ildar · September 29, 2012 at 8:21 AM

I don’t think that using of literals “as is” is good idea. Look, the example below.

(new Date()).format(‘I have tried it at HH:mm:ss’)

Maybe the better way is metacharacters in php style like “%char” or in java style like “{char}”

    Chris West · September 29, 2012 at 9:06 PM

    To do what you are asking for, I would try the following instead:
    [code language=javascript]
    (new Date).format("'I have tried it at' HH:mm:ss")
    [/code]

    Try to put this string into the input box in the JSBin example:
    [code language=plain]
    'I have tried it at' HH:mm:ss
    [/code]

      ildar · October 1, 2012 at 12:25 AM

      Aha! There are single quotes to escape processing of a part of a string. I did not see them first time.

Chris West · January 7, 2013 at 1:01 PM

I just realized that I had an issue with using single quotes to escape empty strings or 1 character strings. I have fixed this issue in both the JSBin example and the code source.

Leave a Reply to ildar Cancel reply

Your email address will not be published. Required fields are marked *