
 /**
  *     date.prototype.js
  *     -----------------
  * 
  *   @author "Cau Guanabara" <caugb@ibest.com.br>
	*   @date 2006-09-05
  * 
  *   This file add some functions to the Date() object, to:
  *   ------------------------------------------------------
	*     -> format dates starting from a string given by user
	*     -> configure any language to the literal return values
  *     -> get the local time-zone (in hours, minutes or seconds)
  *     -> format dates according to the RFC-2822 / RFC-3339
	*/


// lang properties //

// work language
Date.prototype.lang = 'en';

// lower case week days
Date.prototype.dayNames = {
	'pt-br': ['domingo', 'segunda-feira', 'ter&ccedil;a-feira', 'quarta-feira', 'quinta-feira', 'sexta-feira', 's&aacute;bado'],
  'en':    ['sunday', 'monday', 'tuesday', 'wednesday', 'thursday', 'friday', 'saturday'] 
};

// lower case months
Date.prototype.monthNames = {
	'pt-br': ['janeiro', 'fevereiro', 'mar&ccedil;o', 'abril', 'maio', 'junho', 
			      'julho', 'agosto', 'setembro', 'outubro', 'novembro', 'dezembro'],
	'en':    ['january', 'february', 'march', 'april', 'may', 'june', 'july', 
				    'august', 'september', 'october', 'november', 'december']
};

// return a date string
Date.prototype.toFormattedString = function(str, lcase) {
var day = this.getDate(), month = this.getMonth(), wdayn = this.getDay(),
    year = this.getFullYear(), hours = this.getHours(), hours12 = hours,
		ap = 'am', minutes = this.getMinutes(), seconds = this.getSeconds(),
		tz = this.getTimezoneOffset(); 
		
  if(hours > 12) { ap = 'pm'; hours12 = hours - 12; }
	
this.values = {
	'd': day < 10 ? '0'+day : day,                 // dia do mes (01-31)
	'j': day,                                      // dia do mes (1-31)
	'h': hours12 < 10 ? '0'+hours12 : hours12,     // horas (01-12)
	'H': hours < 10 ? '0'+hours : hours,           // horas (00-23)
	'g': hours12,                                  // horas (1-12)
	'G': hours,                                    // horas (0-23)
	'i': minutes < 10 ? '0'+minutes : minutes,     // minutos (00-59)
	'm': month < 10 ? '0'+(month + 1) : month + 1, // mes (01-12)
	'n': month,                                    // mes (1-12)
	's': seconds < 10 ? '0'+seconds : seconds,     // segundos (00-59)
	'w': wdayn,                                    // dia da semana (0(dom)-6(sab))
	'y': String(year).substr(2,2),                 // ano 2 dígitos
	'Y': year,                                     // ano 4 dígitos
	'U': this.getTime(),                           // segundos desde 1970-01-01 00:00:00
	'Z': tz > 0 ? '+'+tz : tz,                     // time zone
	'a': ap,                                       // am-pm
	'A': ap.toUpperCase().replace(/M/,'&#77;'),    // AM-PM (replace para evitar a próx. subst.)
	'M': /m/.test(lcase) ?                         // mes (jan-dez)
	       this.monthNames[this.lang][month].substr(0,3) : 
	       this.monthNames[this.lang][month].substr(0,3).UCFirst(),
	'D': /d/.test(lcase) ?                         // dia da semana (seg-dom)
	       this.dayNames[this.lang][wdayn].substr(0,3) : 
         this.dayNames[this.lang][wdayn].substr(0,3).UCFirst(),
	'F': /m/.test(lcase) ?                         // mes (janeiro-dezembro)
	       this.monthNames[this.lang][month] :
	       this.monthNames[this.lang][month].UCFirst(),
	'l': /d/.test(lcase) ?                         // dia da semana (domingo-sábado)
	       this.dayNames[this.lang][wdayn] : 
         this.dayNames[this.lang][wdayn].UCFirst() 
};

var outputStr = str.replace(/\\([aAdDFgGhHijlmMnsUwyYZ])/g, 
														function(str, s1) { return '&#'+s1.charCodeAt(0)+';'; });
  
	for(var i in this.values) 
	  outputStr = outputStr.replace(new RegExp(i,'g'), this.values[i]);

outputStr = outputStr.replace(/&#(\d+);/g,
															function(str, s1) { return String.fromCharCode(Number(s1)); });
return outputStr;
}

// adds a new language
Date.prototype.addLang = function(lang, days, months) { 
 if(!/^\w+$/.test(lang) || days.length != 7 || months.length != 12) return false;
days.walk(function(x) { return x.toLowerCase(); });
months.walk(function(x) { return x.toLowerCase(); });
this.dayNames[lang] = days;
this.monthNames[lang] = months;
return true;
};

// selects the work language 
Date.prototype.setLang = function(lng) { 
  if(!(this.dayNames[lng] || false) || !(this.monthNames[lng] || false)) return false; 
this.lang = lng;
return true;
};

// time zone
Date.prototype.getTimezone = function(typ, sgn) { 
var mns = this.getTimezoneOffset();
var mins = Math.abs(mns);
var hours = mins / 60;
var rmins = mins % 60;
var secs = mns * 60;
var sign = sgn? (mns > 0 ? '+' : '-') : '';
hours = hours < 10 ? '0'+hours : hours;
rmins = rmins < 10 ? '0'+rmins : rmins;
  switch(typ) {
		case "seconds": case "sec": return sign+secs;
		case "minutes": case "min": return sign+mns;
    default: return sign+hours+':'+rmins;
  }
};

// RFC 2822 formatting
Date.prototype.toRFC2822 = function() { 
var olang = this.lang;
this.setLang('en');                           // por q o nome do dia chega minusculo???
var ret = this.toFormattedString('D, j M H:i:s ').UCFirst()+this.getTimezone('hour',1);
this.setLang(olang);
return ret;
};

// RFC 3339 formatting
Date.prototype.toRFC3339 = function(notz) { 
var timezone = notz ? 'Z' : this.getTimezone('hour',1);
return this.toFormattedString('Y-m-dTH:i:s')+timezone;
};

// keeps the object up to date
Date.prototype.setClock = function(msecs, func) {
var mscs = (msecs || 1000), funcp = '', nd = new Date();
this.setTime(nd.getTime());
  if(func) { funcp = ', "'+func+'"'; new Function(func)(); } 
_dateObjSelfReference = this;
setTimeout('_dateObjSelfReference.setClock('+msecs+funcp+');', mscs);
};

// Other support .prototype methods //

// Transforms the first letter of the string to upper case
String.prototype.UCFirst = function() {
  if(!(/^([a-zA-Z])([\w\W.]*)$/.test(this))) return this;
return RegExp.$1.toUpperCase() + RegExp.$2;
}

// Applies a given function to all elements of the array
Array.prototype.walk = function(func) {
	for(var i = 0; i < this.length; i++) this[i] = (func(this[i]) || this[i]);
};