A lot of people probably already know PHPs date formatting system and are quite familiar with it. Using formatting strings like “Y-m-d H:i:s” makes it really easy to produce nicely formatted date strings in a way that is relatively easy to remember since you probably use the same few formatting strings all the time. In combination with the much improved DateTime class in PHP 5.3 this gives you all the tools you need to work with dates and timestamps.
JavaScript has a very powerful and comfortable Date object, too. The only thing that’s missing is an output formatting method that doesn’t involve concatenating the strings from the single outputs of the Date object together manually.
So here it is: An extension of the Date object that replicates the functionality of PHPs formatting system:
/*
* The following call returns a closure which has some helper functions and objects in it's scope.
* The closure is then added to the Date prototype and will be available in all Date objects as the "format" method.
*/
Date.prototype.format = (function () {
/*
* Helper function for padding numbers with zeros on the left side
* @private
* @param {Number} number The input number that is to be padded
* @param {Number} digits The number of digits of the resulting number
* @return {String}
*/
var pad = function(number, digits) {
var padding = '';
while ((number + padding).length < digits) {
padding += '0';
}
return padding + number;
};
var weekDaysShort = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
var weekDaysLong = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
var monthsShort = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
/*
* Helper method to determine if an hour in 24h format is AM or PM
* @param {Number} h The hour in 24h Format
* @return {String}
* @private
*/
var amPm = function(h) {
if (h<=12) {
return 'am';
} else {
return 'pm';
}
};
/*
* Constructor for the replacer object that provides methods for the format placeholders
* @param {Date} The Date object that serves a s adata source for the string replacements
* @constructor
*/
var Replacer = function(d) {
this.dO = d; //makes the passed Date object available to the Replacers prototype
};
Replacer.prototype = {
d: function () {return pad(this.dO.getDate(), 2);},
D: function () {return weekDaysShort[this.dO.getDay()];},
j: function () {return this.dO.getDate();},
l: function () {return weekDaysLong[this.dO.getDay()];},
N: function () {return this.dO.getDay()+1;},
S: function () {
var n = this.dO.getDate();
if (n == 11 || n==12 || n==13) {
return 'st';
}
n = n % 10;
switch (n) {
case 1: return 'st';
break;
case 2: return 'nd';
break;
case 3: return 'rd';
break;
default: return 'th';
}
},
w: function () {return this.dO.getDay();},
m: function () {return pad(this.dO.getMonth(),2);},
M: function () {return monthsShort[this.dO.getMonth()];},
n: function () {return this.dO.getMonth()+1;},
Y: function () {return this.dO.getFullYear();},
y: function () {return this.dO.getFullYear().toString().substr(2);},
a: function () {return amPm(this.dO.getHours());},
A: function () {return amPm(this.dO.getHours()).toUpperCase();},
g: function () {return this.dO.getHours() % 12;},
G: function () {return this.dO.getHours();},
h: function () {return pad(this.dO.getHours() % 12, 2);},
H: function () {return pad(this.dO.getHours(),2);},
i: function () {return pad(this.dO.getMinutes(),2);},
s: function () {return pad(this.dO.getSeconds(),2);},
U: function () {return this.dO.getTime();}
};
/*
* Returns a closure that has all the needed private helpers in it's scope.
*/
return function (format) {
var returnString = '';
var replacer = new Replacer(this);
for (var i = 0; i < format.length; i = i + 1) {
if (typeof replacer[format[i]] !== 'undefined') {
returnString += replacer[format[i]]();
} else {
returnString += format[i];
}
}
return returnString;
};
}());
After executing this piece of code, all your Date objects will have a format() method. Even the ones that have been created earlier due to JavaScripts prototypal inheritance system.
You can call the format() method with a formatting string just like in PHP. It uses the same tokens to represent the individual fields. For a detailed explanation what every token does, please consult the PHP manual page for date().
This version here does not support all the formatting options that are available in PHP but the common ones are in there.
If you need additional formatting options, you can easily extend the formatter by adding new methods to Replacer.prototype where all the tokens for the format string are defined as functions.