Monday, October 15, 2007

JavaScript Date Formatter

We offten need to display date in accordance with some pattern. There is my implementaion of this task for javascript:

SimpleDateFormatter = function() {};

SimpleDateFormatter.zeroize = function (value, length) {
    if (!length) length = 2;
    value = String(value);
    for (var i = 0, zeros = '';
         i < (length - value.length); i++) {
        zeros += '0';
    }
    return zeros + value;
};
SimpleDateFormatter.getTimezome = function (date) {
    if (!date)
        return "";
    var dateStr = date + "";
    var timezoneIndex = dateStr.indexOf("GMT");
    if (timezoneIndex == -1)
        timezoneIndex = dateStr.indexOf("UTC");
    if (timezoneIndex > 0) {
        return dateStr.substring(timezoneIndex, dateStr.length);
    }
    return "";
}
SimpleDateFormatter.getFromCache = function (pattern){
    if (SimpleDateFormatter.cache && SimpleDateFormatter.cache[pattern])
        return SimpleDateFormatter.cache[pattern];
    return null;
}
SimpleDateFormatter.putToCache = function (pattern, func) {
    if (SimpleDateFormatter.cache)
        SimpleDateFormatter.cache[pattern] = func;
}
SimpleDateFormatter.formatter = function(pattern)
{
    //remove quortes to avoid function compilation problems
    pattern = pattern.replace(/'/g, "");
    pattern = pattern.replace(/\n/g,"\\n");
    var cached = SimpleDateFormatter.getFromCache(pattern);
    if (cached)
        return cached;

    pattern = "'"+pattern+"'";
    var funcSrc = pattern.replace(/(yyyy|MMMM|MMM|MM|M|EEEE|EEE|dd|d|hh|h|kk|k|mm|m|ss|s|S|z)/g,
        function($1)
        {
            switch ($1)
            {
            case 'yyyy': return "'+date.getFullYear()+'";
            case 'MMMM': return "'+SimpleDateFormatter.monthNames[date.getMonth()]+'";
            case 'MMM':  return "'+SimpleDateFormatter.monthNames[date.getMonth()].substr(0, 3)+'";
            case 'MM':   return "'+SimpleDateFormatter.zeroize(date.getMonth() + 1)+'";
            case 'M':   return "'+(date.getMonth() + 1)+'";
            case 'EEEE': return "'+SimpleDateFormatter.dayNames[date.getDay()]+'";
            case 'EEE':  return "'+SimpleDateFormatter.dayNames[date.getDay()].substr(0, 3)+'";
            case 'dd':   return "'+SimpleDateFormatter.zeroize(date.getDate())+'";
            case 'd':   return "'+date.getDate()+'";
            case 'h':   return "'+date.getHours()+'";
            case 'hh':   return "'+SimpleDateFormatter.zeroize(date.getHours())+'";
            case 'k':   return "'+((h = date.getHours() % 12) ? h : '12')+(date.getHours() < 12 ? 'am' : 'pm')+'";
            case 'kk':   return "'+SimpleDateFormatter.zeroize((h = date.getHours() % 12) ? h : '12')+(date.getHours() < 12 ? 'am' : 'pm')+'";
            case 'mm':   return "'+SimpleDateFormatter.zeroize(date.getMinutes())+'";
            case 'm':   return "'+date.getMinutes()+'";
            case 'ss':   return "'+SimpleDateFormatter.zeroize(date.getSeconds())+'";
            case 's':   return "'+date.getSeconds()+'";
            case 'S':   return "'+date.getMilliseconds()+'";
            case 'z':   return "'+SimpleDateFormatter.getTimezome(date)+'";
            }
        }
        );

    funcSrc = "return "+funcSrc;
    var func = new Function("date", funcSrc);
    SimpleDateFormatter.putToCache(pattern, func);
    return func;
}

// a global month names array
SimpleDateFormatter.monthNames = new Array(
        'January',
        'February',
        'March',
        'April',
        'May',
        'June',
        'July',
        'August',
        'September',
        'October',
        'November',
        'December'
        );

// a global day names array
SimpleDateFormatter.dayNames = new Array(
        'Sunday',
        'Monday',
        'Tuesday',
        'Wednesday',
        'Thursday',
        'Friday',
        'Saturday'
        );

//cache: pattern->format function
SimpleDateFormatter.cache = {};
Pattern letters
y Year 1996; 96
M Month in year July; Jul; 07
d Day in month 10
E Day in week Tuesday; Tue
H Hour in day (0-23) 0
K Hour in am/pm (0-11) 0
m Minute in hour (0-59) 30
s Second in minute (0-59) 55
S Millisecond (0-999) 978
z Time zone GMT+04:00

Usage Now you may use it:
var formatter = SimpleDateFormatter.formatter("yyyy/MMM/EEE");//formatter is a function
alert(formatter(new Date()));
We also use cache of formatter, so you could use SimpleDateFormatter.formatter("yyyy/MMM/EEE")(date) everywhere, and formatter function will be created only single time.
Year(yyyy)Month(M)Day(d)Hour(h)Minutes(m)Seconds(s)Milliseconds(S)
Pattern

No comments: