Zapatec Calendar Overview

Overview | File | Class | Tree | Index | Help

Zapatec Calendar

PREV NEXT | FRAMES NO FRAMES

## calendar-date-core.js

#### Summary

No overview generated for 'calendar-date-core.js'

    /* $Id: calendar-date-core.js 6805 2007-03-30 12:36:39Z slip $ */
    /**
     *
     * Copyright (c) 2004-2006 by Zapatec, Inc.
     * http://www.zapatec.com
     * 1700 MLK Way, Berkeley, California,
     * 94709, U.S.A.
     * All rights reserved.
     */

    // BEGIN: DATE OBJECT PATCHES

    /** \defgroup DateExtras Augmenting the Date object with some utility functions
     * and variables.
     */
    //@{

    Date._MD = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; /**< Number of days in each month */

    Date.SECOND = 1000;		/**< One second has 1000 milliseconds. */
    Date.MINUTE = 60 * Date.SECOND;	/**< One minute has 60 seconds. */
    Date.HOUR   = 60 * Date.MINUTE;	/**< One hour has 60 minutes. */
    Date.DAY    = 24 * Date.HOUR;	/**< One day has 24 hours. */
    Date.WEEK   =  7 * Date.DAY;	/**< One week has 7 days. */

    /** Returns the number of days in the month.  The \em month parameter is
     * optional; if not passed, the current month of \b this Date object is
     * assumed.
     *
     * @param month [int, optional] the month number, 0 for January.
     */
    Date.prototype.getMonthDays = function(month) {
    	var year = this.getFullYear();
    	if (typeof month == "undefined") {
    		month = this.getMonth();
    	}
    	if (((0 == (year%4)) && ( (0 != (year%100)) || (0 == (year%400)))) && month == 1) {
    		return 29;
    	} else {
    		return Date._MD[month];
    	}
    };

    /** Returns the number of the current day in the current year. */
    Date.prototype.getDayOfYear = function() {
    	var now = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
    	var then = new Date(this.getFullYear(), 0, 0, 0, 0, 0);
    	var time = now - then;
    	return Math.round(time / Date.DAY);
    };

    /** Returns the number of the week in year, as defined in ISO 8601. */
    Date.prototype.getWeekNumber = function() {
    	var d = new Date(this.getFullYear(), this.getMonth(), this.getDate(), 0, 0, 0);
    	var DoW = d.getDay();
    	d.setDate(d.getDate() - (DoW + 6) % 7 + 3); // Nearest Thu
    	var ms = d.valueOf(); // GMT
    	d.setMonth(0);
    	d.setDate(4); // Thu in Week 1
    	return Math.round((ms - d.valueOf()) / (7 * 864e5)) + 1;
    };

    /** Checks dates equality.  Checks time too. */
    Date.prototype.equalsTo = function(date) {
    	return ((this.getFullYear() == date.getFullYear()) &&
    		(this.getMonth() == date.getMonth()) &&
    		(this.getDate() == date.getDate()) &&
    		(this.getHours() == date.getHours()) &&
    		(this.getMinutes() == date.getMinutes()));
    };

    /** Checks dates equality.  Ignores time. */
    Date.prototype.dateEqualsTo = function(date) {
    	return ((this.getFullYear() == date.getFullYear()) &&
    		(this.getMonth() == date.getMonth()) &&
    		(this.getDate() == date.getDate()));
    };

    /** Set only the year, month, date parts (keep existing time) */
    Date.prototype.setDateOnly = function(date) {
    	var tmp = new Date(date);
    	this.setDate(1);
    	this.setFullYear(tmp.getFullYear());
    	this.setMonth(tmp.getMonth());
    	this.setDate(tmp.getDate());
    };

    /** Prints the date in a string according to the given format.
     *
     * The format (\b str) may contain the following specialties:
     *
     * - %%a - Abbreviated weekday name
     * - %%A - Full weekday name
     * - %%b - Abbreviated month name
     * - %%B - Full month name
     * - %%C - Century number
     * - %%d - The day of the month (00 .. 31)
     * - %%e - The day of the month (0 .. 31)
     * - %%H - Hour (00 .. 23)
     * - %%I - Hour (01 .. 12)
     * - %%j - The day of the year (000 .. 366)
     * - %%k - Hour (0 .. 23)
     * - %%l - Hour (1 .. 12)
     * - %%m - Month (01 .. 12)
     * - %%M - Minute (00 .. 59)
     * - %%n - A newline character
     * - %%p - "PM" or "AM"
     * - %%P - "pm" or "am"
     * - %%S - Second (00 .. 59)
     * - %%s - Number of seconds since Epoch
     * - %%t - A tab character
     * - %%W - The week number (as per ISO 8601)
     * - %%u - The day of week (1 .. 7, 1 = Monday)
     * - %%w - The day of week (0 .. 6, 0 = Sunday)
     * - %%y - Year without the century (00 .. 99)
     * - %%Y - Year including the century (ex. 1979)
     * - %%% - A literal %% character
     *
     * They are almost the same as for the POSIX strftime function.
     *
     * @param str [string] the format to print date in.
     */
    Date.prototype.print = function (str) {
    	var m = this.getMonth();
    	var d = this.getDate();
    	var y = this.getFullYear();
    	var wn = this.getWeekNumber();
    	var w = this.getDay();
    	var s = {};
    	var hr = this.getHours();
    	var pm = (hr >= 12);
    	var ir = (pm) ? (hr - 12) : hr;
    	var dy = this.getDayOfYear();
    	if (ir == 0)
    		ir = 12;
    	var min = this.getMinutes();
    	var sec = this.getSeconds();
    	s["%a"] = Zapatec.Calendar.i18n(w, "sdn"); // abbreviated weekday name [FIXME: I18N]
    	s["%A"] = Zapatec.Calendar.i18n(w, "dn"); // full weekday name
    	s["%b"] = Zapatec.Calendar.i18n(m, "smn"); // abbreviated month name [FIXME: I18N]
    	s["%B"] = Zapatec.Calendar.i18n(m, "mn"); // full month name
    	// FIXME: %c : preferred date and time representation for the current locale
    	s["%C"] = 1 + Math.floor(y / 100); // the century number
    	s["%d"] = (d < 10) ? ("0" + d) : d; // the day of the month (range 01 to 31)
    	s["%e"] = d; // the day of the month (range 1 to 31)
    	// FIXME: %D : american date style: %m/%d/%y
    	// FIXME: %E, %F, %G, %g, %h (man strftime)
    	s["%H"] = (hr < 10) ? ("0" + hr) : hr; // hour, range 00 to 23 (24h format)
    	s["%I"] = (ir < 10) ? ("0" + ir) : ir; // hour, range 01 to 12 (12h format)
    	s["%j"] = (dy < 100) ? ((dy < 10) ? ("00" + dy) : ("0" + dy)) : dy; // day of the year (range 001 to 366)
    	s["%k"] = hr ? hr :  "0"; // hour, range 0 to 23 (24h format)
    	s["%l"] = ir;		// hour, range 1 to 12 (12h format)
    	s["%m"] = (m < 9) ? ("0" + (1+m)) : (1+m); // month, range 01 to 12
    	s["%M"] = (min < 10) ? ("0" + min) : min; // minute, range 00 to 59
    	s["%n"] = "\n";		// a newline character
    	s["%p"] = pm ? "PM" : "AM";
    	s["%P"] = pm ? "pm" : "am";
    	// FIXME: %r : the time in am/pm notation %I:%M:%S %p
    	// FIXME: %R : the time in 24-hour notation %H:%M
    	s["%s"] = Math.floor(this.getTime() / 1000);
    	s["%S"] = (sec < 10) ? ("0" + sec) : sec; // seconds, range 00 to 59
    	s["%t"] = "\t";		// a tab character
    	// FIXME: %T : the time in 24-hour notation (%H:%M:%S)
    	s["%U"] = s["%W"] = s["%V"] = (wn < 10) ? ("0" + wn) : wn;
      s["%u"] = (w == 0) ? 7 : w; // the day of the week (range 1 to 7, 1 = MON)
    	s["%w"] = w ? w : "0";		// the day of the week (range 0 to 6, 0 = SUN)
    	// FIXME: %x : preferred date representation for the current locale without the time
    	// FIXME: %X : preferred time representation for the current locale without the date
    	s["%y"] = '' + y % 100; // year without the century (range 00 to 99)
    	if (s["%y"] < 10) {
    		s["%y"] = "0" + s["%y"];
    	}
    	s["%Y"] = y;		// year with the century
    	s["%%"] = "%";		// a literal '%' character

    	var re = /%./g;
    	var a = str.match(re) || [];
    	for (var i = 0; i < a.length; i++) {
    		var tmp = s[a[i]];
    		if (tmp) {
    			re = new RegExp(a[i], 'g');
    			str = str.replace(re, tmp);
    		}
    	}

    	return str;
    };

    /**
     * Parses a date from a string in the specified format.
     * This function requires strict following of the string to
     * the format template, and any difference causes failure
     * to be returned. Also function refuses to parse formats
     * which containing number rules that have not fixed length
     * and are not separated from the next number rule by any
     * character string, as this requires complication of algorythm
     * and still sometimes is impossible to parse.
     *
     * @param str [string] the date as a string
     * @param format [string] the format to try to parse the date in
     *
     * @return [Date] a date object containing the parsed date or \b null if for
     * some reason the date couldn't be parsed.
     */
    Date.parseDate = function (str, format) {
    	var fmt = format, strPointer = 0, token = null, parseFunc = null, valueLength = null,
    	valueRange = null, valueType = null, date = new Date(), values = {};
    	//need to have a way to determine whether rule is number
    	var numberRules = ["%d", "%H", "%I", "%m", "%M", "%S", "%s", "%W", "%u",
    	                       "%w", "%y", "%e", "%k", "%l", "%s", "%Y", "%C"];
    	function isNumberRule(rule) {
    		if (Zapatec.Utils.arrIndexOf(numberRules, rule) != -1) {
    			return true;
    		}
    		return false;
    	}
    	//parses string value from translation table
    	function parseString() {
    		for(var iString = valueRange[0]; iString < valueRange[1]; ++iString) {
    			//checking if there is translation
    			var value = Zapatec.Calendar.i18n(iString, valueType);
    			if (!value) {
    				return null;
    			}
    			//comparing with our part of the string
    			if (value == str.substr(strPointer, value.length)) {
    				//increasing string pointer
    				valueLength = value.length;
    				return iString;
    			}
    		}
    		return null;
    	}
    	//parses the number from beginning of string
    	function parseNumber() {
    		var val = str.substr(strPointer, valueLength);
    		if (val.length != valueLength || /$\d+^/.test(val)) {
    			return null;
    		}
    		return parseInt(val, 10);
    	}
    	//parses AM PM rule
    	function parseAMPM() {
    		var result = (str.substr(strPointer, valueLength).toLowerCase() == Zapatec.Calendar.i18n("pm", "ampm")) ? true : false;
    		return result || ((str.substr(strPointer, valueLength).toLowerCase() == Zapatec.Calendar.i18n("am", "ampm")) ? false : null);
    	}
    	//parses formating character
    	function parseCharacter() {
    		return "";
    	}
    	//parses the rule to the array
    	function parseRule(rule) {
    		return (values[rule] = parseFunc());
    	}
    	//function determines if rule value was parsed
    	function wasParsed(rule) {
    		if (typeof rule == "undefined" || rule === null) {
    			return false;
    		}
    		return true;
    	}
    	//gets first defined value or null if no
    	function getValue() {
    		for(var i = 0; i < arguments.length; ++i) {
    			if (arguments[i] !== null && typeof arguments[i] != "undefined" && !isNaN(arguments[i])) {
    				return arguments[i];
    			}
    		}
    		return null;
    	}
    	if (typeof fmt != "string" || typeof str != "string" || str == "" || fmt == "") {
    		return null;
    	}
    	//cycle breaks format into tokens and checks or parses them
    	while(fmt) {
    		//this is the default value type
    		parseFunc = parseNumber;
    		//taking char token(that doesn't hold any information)
    		valueLength = fmt.indexOf("%");
    		valueLength = (valueLength == -1) ? fmt.length : valueLength;
    		token = fmt.slice(0, valueLength);
    		//checking if we have same token in parsed string
    		if (token != str.substr(strPointer, valueLength)) {
    			return null;
    		}
    		//skiping it
    		strPointer += valueLength;
    		fmt = fmt.slice(valueLength);
    		if (fmt == "") {
    			break;
    		}
    		//taking formating rule
    		token = fmt.slice(0, 2);
    		//this is the default length of value, as it is very often one for rules
    		valueLength = 2;
    		switch (token) {
    			case "%A" :
    			case "%a" : {
    				valueType = (token == "%A") ? "dn" : "sdn";
    				valueRange = [0, 7];
    				parseFunc = parseString;
    				break;
    			}
    			case "%B" :
    			case "%b" : {
    				valueType = (token == "%B") ? "mn" : "smn";
    				valueRange = [0, 12];
    				parseFunc = parseString;
    				break;
    			}
    			case "%p" :
    			case "%P" : {
    				parseFunc = parseAMPM;
    				break;
    			}
    			case "%Y" : {
    				valueLength = 4;
    				if (isNumberRule(fmt.substr(2, 2))) {
    					return null;
    				}
    				while(isNaN(parseInt(str.charAt(strPointer + valueLength - 1))) && valueLength > 0) {
    					--valueLength;
    				}
    				if (valueLength == 0) {break;}
    				break;
    			}
    			case "%C" :
    			case "%s" : {
    				valueLength = 1;
    				if (isNumberRule(fmt.substr(2, 2))) {
    					return null;
    				}
    				while(!isNaN(parseInt(str.charAt(strPointer + valueLength)))) {
    					++valueLength;
    				}
    				break;
    			}
    			case "%k" :
    			case "%l" :
    			case "%e" : {
    				valueLength = 1;
    				if (isNumberRule(fmt.substr(2, 2))) {
    					return null;
    				}
    				if (!isNaN(parseInt(str.charAt(strPointer + 1)))) {
    					++valueLength;
    				}
    				break;
    			}
    			case "%j" : valueLength = 3; break;
    			case "%u" :
    			case "%w" : valueLength = 1;
    			case "%y" :
    			case "%m" :
    			case "%d" :
    			case "%W" :
    			case "%H" :
    			case "%I" :
    			case "%M" :
    			case "%S" : {
    				break;
    			}
    		}
    		if (parseRule(token) === null) {
    			return null;
    		}
    		//increasing pointer
    		strPointer += valueLength;
    		//skipint it
    		fmt = fmt.slice(2);
    	}
    	if (wasParsed(values["%s"])) {
    		date.setTime(values["%s"] * 1000);
    	} else {
    		var year = getValue(values["%Y"], values["%y"] + --values["%C"] * 100,
    		                    values["%y"] + (date.getFullYear() - date.getFullYear() % 100),
    		                    values["%C"] * 100 + date.getFullYear() % 100);
    		var month = getValue(values["%m"] - 1, values["%b"], values["%B"]);
    		var day = getValue(values["%d"] || values["%e"]);
    		if (day === null || month === null) {
    			var dayOfWeek = getValue(values["%a"], values["%A"], values["%u"] == 7 ? 0 : values["%u"], values["%w"]);
    		}
    		var hour = getValue(values["%H"], values["%k"]);
    		if (hour === null && (wasParsed(values["%p"]) || wasParsed(values["%P"]))) {
    			var pm = getValue(values["%p"], values["%P"]);
    			hour = getValue(values["%I"], values["%l"]);
    			hour = pm ? ((hour == 12) ? 12 : (hour + 12)) : ((hour == 12) ? (0) : hour);
    		}
    		if (year || year === 0) {
    			date.setFullYear(year);
    		}
    		if (month || month === 0) {
    			date.setMonth(month);
    		}
    		if (day || day === 0) {
    			date.setDate(day);
    		}
    		if (wasParsed(values["%j"])) {
    			date.setMonth(0);
    			date.setDate(1);
    			date.setDate(values["%j"]);
    		}
    		if (wasParsed(dayOfWeek)) {
    			date.setDate(date.getDate() + (dayOfWeek - date.getDay()));
    		}
    		if (wasParsed(values["%W"])) {
    			var weekNumber = date.getWeekNumber();
    			if (weekNumber != values["%W"]) {
    				date.setDate(date.getDate() + (values["%W"] - weekNumber) * 7);
    			}
    		}
    		if (hour !== null) {
    			date.setHours(hour);
    		}
    		if (wasParsed(values["%M"])) {
    			date.setMinutes(values["%M"]);
    		}
    		if (wasParsed(values["%S"])) {
    			date.setSeconds(values["%S"]);
    		}
    	}
    	//printing date in the same format and checking if we'll get the same string
    	if (date.print(format) != str) {
    		//if not returning error
    		return null;
    	}
    	//or returning parsed date
    	return date;
    };

    Date.prototype.__msh_oldSetFullYear = Date.prototype.setFullYear; /**< save a reference to the original setFullYear function */

    /**
     * This function replaces the original Date.setFullYear() with a "safer"
     * function which makes sure that the month or date aren't modified (unless in
     * the exceptional case where the date is February 29 but the new year doesn't
     * contain it).
     *
     * @param y [int] the new year to move this date to
     */
    Date.prototype.setFullYear = function(y) {
    	var d = new Date(this);
    	d.__msh_oldSetFullYear(y);
    	if (d.getMonth() != this.getMonth())
    		this.setDate(28);
    	this.__msh_oldSetFullYear(y);
    };

    /**
     * This function compares only years, months and days of two date objects.
     *
     * @return [int] -1 if date1>date2, 1 if date2>date1 or 0 if they are equal
     *
     * @param date1 [Date] first date to compare
     * @param date1 [Date] second date to compare
     */
    Date.prototype.compareDatesOnly = function (date1,date2) {
    	var year1 = date1.getYear();
    	var year2 = date2.getYear();
    	var month1 = date1.getMonth();
    	var month2 = date2.getMonth();
    	var day1 = date1.getDate();
    	var day2 = date2.getDate();
    	if (year1 > year2) { return -1;	}
    	if (year2 > year1) { return 1; } //years are equal
    	if (month1 > month2) { return -1; }
    	if (month2 > month1) { return 1; } //years and months are equal
    	if (day1 > day2) { return -1; }
    	if (day2 > day1) { return 1; } //days are equal
    	return 0;
    }

    //@}

    // END: DATE OBJECT PATCHES

Overview | File | Class | Tree | Index | Help

Zapatec Calendar

PREV NEXT | FRAMES NO FRAMES

Documentation generated by JSDoc on Thu Aug 16 12:18:51 2007