/* DateFormat.js: formats JavaScript Dates. Copyright (C) 1999 Jan Wessely This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License Version 2 as published by the Free Software Foundation. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA or browse to http://www.gnu.org/copyleft/gpl.html. Created: 27 Dec 1999 Last modified: 25 Sep 2000 */ // constructors *************************************************************** // DateFormat() // DateFormat(string pattern, opt Locale locale) // DateFormat(number dateStyle, opt number timeStyle, opt string locale) function DateFormat() { var argv = DateFormat.arguments; var argc = argv.length; if(argc == 0) { this.pattern = ""; this.locale = Locale.availableLocales[Locale.DEFAULT]; } else if(typeof argv[0] == "string") { this.pattern = argv[0]; this.locale = (argc >= 2) ? argv[2] : Locale.availableLocales[Locale.DEFAULT]; } else { this.locale = argc >= 3 && argv[2] ? argv[2] : Locale.availableLocales[Locale.DEFAULT]; this.setStyle(argv[0], argc > 1 ? argv[1] : DateFormat.NONE); } } // methods ******************************************************************** function /*string*/ _DateFormat_format(/*Date*/ date) { //sanity check if(!date) return ""; if(typeof date == "string") date = new Date(date); var s = ""; var pos = 0; while(pos < this.pattern.length) { var c = this.pattern.charAt(pos); var length; var symbol = DateFormat.SYMBOLS[c]; if(symbol) { length = this._consume(pos, c); s += symbol.format(date, length, this.locale); } else if(c == "'") { if(pos >= this.pattern.length - 1) // last char { length = 1; s += c; } else if(this.pattern.charAt(pos + 1) != "'") // delim, not escape { var eos = this.pattern.indexOf("'", ++pos); if(eos == -1) eos = this.pattern.length; // don''t be anal length = (eos - pos) + 1; s += this.pattern.substring(pos, eos); } else // escape { length = 2; s += c; } } else // treat any other char as literal { length = 1; s += c; } pos += length; } // while return s; } function _DateFormat_setStyle(/*number*/ dateStyle, /*number*/ timeStyle) { dateStyle = parseInt(dateStyle); timeStyle = parseInt(timeStyle); this.pattern = this.locale.datePattern[dateStyle]; if(this.pattern && timeStyle) this.pattern += " "; this.pattern += this.locale.timePattern[timeStyle]; } // private methods ************************************************************ // returns number of same chars as c in this.pattern starting with pos function _DateFormat_consume(pos, c) { var i = pos; while(++i < this.pattern.length) if(this.pattern.charAt(i) != c) break; return i - pos; } // pads a number with leading zeros so that it has at least l digits function _DateFormat_formatNumber(n, l, locale) { var s = ""; var digits = (new String(n)).length; var zeros = Math.max(0, l - digits); for(var i = 0; i < zeros; i++) s += "0"; return s + n; } function _DateFormat_formatEra(year, l, locale) { var era = year < 0 ? DateFormat.BC : DateFormat.AD; return locale.era[era]; } function _DateFormat_formatMonth(month, l, locale) { if(l < 3) return DateFormat._formatNumber(month + 1, l, locale); else { var months = l == 3 ? locale.shortMonths : locale.longMonths; return months[month]; } } function _DateFormat_formatWeekday(weekday, l, locale) { var weekdays = l < 4 ? locale.shortWeekdays : locale.longWeekdays; return weekdays[weekday]; } function _DateFormat_formatAMPM(hour, l, locale) { var ampm = hour <= 12 && hour > 0 ? DateFormat.AM : DateFormat.PM; return locale.amPm[ampm]; } function _DateFormat_formatTimezone(offset, l, locale) { // todo localized Timezone names var diff = Math.abs(offset); var hours = DateFormat._formatNumber(parseInt(diff / 60), 2); var minutes = DateFormat._formatNumber(diff % 60, 2); return "GMT" + (offset > 0 ? "-" : "+") + hours + ":" + minutes; } function _DateFormat_formatMillis(date, l, locale) { var date2 = new Date(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()); return DateFormat._formatNumber(date.getTime() - date2.getTime(), l, locale); } function _DateFormat_formatYear(date, l, locale) { var year = date.getYear(); var fullYear = date.getFullYear(); if(year != fullYear && year == 100) year = 0; var y = l > 2 ? fullYear : year; return DateFormat._formatNumber(y, l, locale); } DateFormat.NONE = 0; DateFormat.SHORT = 1; DateFormat.MEDIUM = 2; DateFormat.LONG = 3; DateFormat.FULL = 4; DateFormat.NSTYLES = 5; DateFormat.BC = 0; DateFormat.AD = 1; DateFormat.AM = 0; DateFormat.PM = 1; DateFormat._formatNumber = _DateFormat_formatNumber; DateFormat._formatEra = _DateFormat_formatEra; DateFormat._formatMonth = _DateFormat_formatMonth; DateFormat._formatWeekday = _DateFormat_formatWeekday; DateFormat._formatAmPm = _DateFormat_formatAMPM; DateFormat._formatTimzone = _DateFormat_formatTimezone; DateFormat._formatMillis = _DateFormat_formatMillis; DateFormat._formatYear = _DateFormat_formatYear; DateFormat.SYMBOLS = new Object(); DateFormat.SYMBOLS["G"] = new _DFSymbol(DateFormat._formatEra, "date.getFullYear()"); DateFormat.SYMBOLS["y"] = new _DFSymbol(DateFormat._formatYear, "date"); DateFormat.SYMBOLS["M"] = new _DFSymbol(DateFormat._formatMonth, "date.getMonth()"); DateFormat.SYMBOLS["d"] = new _DFSymbol(DateFormat._formatNumber, "date.getDate()"); DateFormat.SYMBOLS["h"] = new _DFSymbol(DateFormat._formatNumber, "date.getHours() > 12 ? date.getHours() - 12 : (date.getHours() > 0 ? date.getHours() : 12)"); DateFormat.SYMBOLS["H"] = new _DFSymbol(DateFormat._formatNumber, "date.getHours()"); DateFormat.SYMBOLS["m"] = new _DFSymbol(DateFormat._formatNumber, "date.getMinutes()"); DateFormat.SYMBOLS["s"] = new _DFSymbol(DateFormat._formatNumber, "date.getSeconds()"); DateFormat.SYMBOLS["S"] = new _DFSymbol(DateFormat._formatMillis, "date"); DateFormat.SYMBOLS["E"] = new _DFSymbol(DateFormat._formatWeekday, "date.getDay()"); DateFormat.SYMBOLS["D"] = new _DFSymbol(); DateFormat.SYMBOLS["F"] = new _DFSymbol(); DateFormat.SYMBOLS["w"] = new _DFSymbol(); DateFormat.SYMBOLS["W"] = new _DFSymbol(); DateFormat.SYMBOLS["a"] = new _DFSymbol(DateFormat._formatAmPm, "date.getHours()"); DateFormat.SYMBOLS["k"] = new _DFSymbol(DateFormat._formatNumber, "date.getHours() + 1"); DateFormat.SYMBOLS["K"] = new _DFSymbol(DateFormat._formatNumber, "date.getHours() > 11 ? date.getHours() - 12 : date.getHours()"); DateFormat.SYMBOLS["z"] = new _DFSymbol(DateFormat._formatTimezone, "date.getTimezoneOffset()"); DateFormat.prototype.format = _DateFormat_format; DateFormat.prototype.setStyle = _DateFormat_setStyle; DateFormat.prototype._consume = _DateFormat_consume; // _DFSymbol *********************************************************** // helper object function _DFSymbol(func, value) { this.func = func; this.value = value; } function _DFSymbol_format(date, l, locale) { return this.func ? this.func(eval(this.value), l, locale) : ""; } _DFSymbol.prototype.format = _DFSymbol_format; // Locale ******************************************************************* function Locale(/*string*/ name, /*opt Locale or string*/ parent) { this.name = name; Locale.availableLocales[this.name] = this; this.shortWeekdays = new Array("", "", "", "", "", "", ""); this.longWeekdays = new Array("", "", "", "", "", "", ""); this.shortMonths = new Array("", "", "", "", "", "", "", "", "", "", "", ""); this.longMonths = new Array("", "", "", "", "", "", "", "", "", "", "", ""); this.era = new Array("", ""); this.amPm = new Array("", ""); this.datePattern = new Array("", "", "", "", ""); this.timePattern = new Array("", "", "", "", ""); if(parent) { if(typeof parent == "string") parent = Locale.availableLocales[parent]; copy(parent.shortWeekdays, this.shortWeekdays); copy(parent.longWeekdays, this.longWeekdays); copy(parent.shortMonths, this.shortMonths); copy(parent.longMonths, this.longMonths); copy(parent.era, this.era); copy(parent.amPm, this.amPm); copy(parent.datePattern, this.datePattern); copy(parent.timePattern, this.timePattern); } } function _Locale_toString() { return this.name; } Locale.prototype.toString = _Locale_toString; Locale.availableLocales = new Object(); // helper functions *********************************************************** // shallow copy function /*Object*/ copy(/*object*/ src, /*opt object*/ dst) { if(!dst) dst = new Object(); for(var prop in src) dst[prop] = src[prop]; return dst; } // Locale definitions ********************************************************* var tmp; Locale.DEFAULT = "en"; tmp = new Locale("en"); tmp.shortWeekdays = new Array("Su", "Mo", "Tu", "We", "Fr", "Sa"); tmp.longWeekdays = new Array("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"); tmp.shortMonths = new Array("Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"); tmp.longMonths = new Array("January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"); tmp.era = new Array("BC", "AD"); tmp.amPm = new Array("AM", "PM"); tmp.datePattern = new Array("", "M/d/yy", "MMM d, yyyy", "MMMM d, yyyy", "EEEE, MMMM d, yyyy"); tmp.timePattern = new Array("", "h:mm a", "h:mm:ss a", "h:mm:ss a z", "h:mm:ss a z"); tmp = new Locale("en_GB", "en"); tmp.datePattern = new Array("", "dd/MM/yy", "dd-MMM-yyyy", "dd MMMM yyyy", "EEEE, dd MMMM yyyy"); tmp.timePattern = new Array("", "HH:mm", "HH:mm:ss", "HH:mm:ss z", "HH:mm:ss o''cloc'k' z"); tmp = new Locale("en_NZ", "en"); tmp.datePattern = new Array("", "dd/MM/yy", "dd MMM yyyy", "dd MMMM yyyy", "EEEE, dd MMMM yyyy"); tmp = new Locale("de"); tmp.shortWeekdays = new Array("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); tmp.longWeekdays = new Array("Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"); tmp.shortMonths = new Array("Jan", "Feb", "Mrz", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"); tmp.longMonths = new Array("Januar", "Februar", "M„rz", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"); tmp.era = new Array("v. Chr.", "n. Chr."); tmp.datePattern = new Array("", "dd.MM.yy", "dd.MM.yyyy", "dd. MMMM yyyy", "d. MMMM yyyy"); tmp.timePattern = new Array("", "HH:mm", "HH:mm:ss", "HH:mm:ss z", "HH:mm:ss U'h'r z"); tmp = new Locale("de_AT", "de"); tmp.shortMonths = new Array("J„n", "Feb", "M„r", "Apr", "Mai", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dez"); tmp.longMonths = new Array("J„nner", "Februar", "M„rz", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"); tmp = new Locale("fr"); tmp.shortWeekdays = new Array("dim.", "lun.", "mar.", "mer.", "jeu.", "ven.", "sam."); tmp.longWeekdays = new Array("dimanche", "lundi", "mardi", "mercredi", "jeudi", "vendredi", "samedi"); tmp.shortMonths = new Array("janv.", "f‚vr.", "mars", "avr.", "mai", "juin", "juil.", "ao–t", "sept.", "oct.", "nov.", "d‚c."); tmp.longMonths = new Array("janvier", "f‚vrier", "mars", "avril", "mai", "juin", "juillet", "ao–t", "septembre", "octobre", "novembre", "d‚cembre"); tmp.era = new Array("BC", "ap. J.-C."); tmp.datePattern = new Array("", "dd/MM/yy", "d MMM yy", "d MMMM yyyy", "EEEE d MMMM yyyy"); tmp.timePattern = new Array("", "HH:mm", "HH:mm:ss", "HH:mm:ss z", "HH 'h' mm z"); tmp = new Locale("it"); tmp.shortWeekdays = new Array("dom", "lun", "mar", "mer", "gio", "ven", "sab"); tmp.longWeekdays = new Array("domenica", "lunedŤ", "martedŤ", "mercoledŤ", "giovedŤ", "venerdŤ", "sabato"); tmp.shortMonths = new Array("gen", "feb", "mar", "apr", "mag", "giu", "lug", "ago", "set", "ott", "nov", "dic"); tmp.longMonths = new Array("gennaio", "febbraio", "marzo", "aprile", "maggio", "giugno", "luglio", "agosto", "settembre", "ottobre", "novembre", "dicembre"); tmp.era = new Array("BC", "dopo Cristo"); tmp.datePattern = new Array("", "dd/MM/yy", "d-MMM-yy", "d MMMM yyyy", "EEEE d MMMM yyyy"); tmp.timePattern = new Array("", "H.mm", "H.mm.ss", "HH.mm.ss z", "HH.mm.ss z"); tmp = new Locale("es"); tmp.shortWeekdays = new Array("dom", "lun", "mar", "mi‚", "jue", "vie", "s b"); tmp.longWeekdays = new Array("domingo", "lunes", "martes", "mi‚rcoles", "jueves", "viernes", "s bado"); tmp.shortMonths = new Array("ene", "feb", "mar", "abr", "may", "jun", "jul", "ago", "sep", "oct", "nov", "dic"); tmp.longMonths = new Array("enero", "febrero", "marzo", "abril", "mayo", "junio", "julio", "agosto", "septiembre", "octubre", "noviembre", "diciembre"); tmp.era = new Array("BC", "AD"); tmp.datePattern = new Array("", "d/MM/yy", "d-MMM-yy", "d 'de' MMMM 'de' yyyy", "EEEE d 'de' MMMM 'de' yyyy"); tmp.timePattern = new Array("", "H:mm", "H:mm:ss", "HH:mm:ss z", "HH'H'mm'' z"); tmp = new Locale("pt"); tmp.shortWeekdays = new Array("Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "S b"); tmp.longWeekdays = new Array("Domingo", "Segunda-feira", "Ter‡a-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "S bado"); tmp.shortMonths = new Array("Jan", "Fev", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"); tmp.longMonths = new Array("Janeiro", "Fevereiro", "Mar‡o", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"); tmp.era = new Array("BC", "AD"); tmp.datePattern = new Array("", "dd-MM-yy", "d/MMM/yy", "d 'de' MMMM 'de' yyyy", "EEEE, d 'de' MMMM 'de' yyyy"); tmp.timePattern = new Array("", "H:mm", "H:mm:ss", "HH:mm:ss z", "HH'H'mm'm' z"); // AlexV: tmp = new Locale("zh", "en"); tmp.datePattern = new Array("", "yy-M-d", "yyyy-M-d", "yyyy d MMMM", "EEEE, yyyy d MMMM"); tmp = new Locale("zh_CN", "zh");