You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1485 lines
56 KiB
1485 lines
56 KiB
|
|
/**
|
|
* @fileOverview Date parsing and formatting operations without extending the Date built-in object.
|
|
* @author Chris Leonello
|
|
* @version #VERSION#
|
|
* @date #DATE#
|
|
*/
|
|
|
|
(function($) {
|
|
|
|
/**
|
|
* @description
|
|
* <p>Object with extended date parsing and formatting capabilities.
|
|
* This library borrows many concepts and ideas from the Date Instance
|
|
* Methods by Ken Snyder along with some parts of Ken's actual code.</p>
|
|
*
|
|
* <p>jsDate takes a different approach by not extending the built-in
|
|
* Date Object, improving date parsing, allowing for multiple formatting
|
|
* syntaxes and multiple and more easily expandable localization.</p>
|
|
*
|
|
* @author Chris Leonello
|
|
* @date #date#
|
|
* @version #VERSION#
|
|
* @copyright (c) 2010-2013 Chris Leonello
|
|
* jsDate is currently available for use in all personal or commercial projects
|
|
* under both the MIT and GPL version 2.0 licenses. This means that you can
|
|
* choose the license that best suits your project and use it accordingly.
|
|
*
|
|
* <p>Ken's original Date Instance Methods and copyright notice:</p>
|
|
* <pre>
|
|
* Ken Snyder (ken d snyder at gmail dot com)
|
|
* 2008-09-10
|
|
* version 2.0.2 (http://kendsnyder.com/sandbox/date/)
|
|
* Creative Commons Attribution License 3.0 (http://creativecommons.org/licenses/by/3.0/)
|
|
* </pre>
|
|
*
|
|
* @class
|
|
* @name jsDate
|
|
* @param {String | Number | Array | Date Object | Options Object} arguments Optional arguments, either a parsable date/time string,
|
|
* a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds],
|
|
* a Date object, or an options object of form {syntax: "perl", date:some Date} where all options are optional.
|
|
*/
|
|
|
|
var jsDate = function () {
|
|
|
|
this.syntax = jsDate.config.syntax;
|
|
this._type = "jsDate";
|
|
this.proxy = new Date();
|
|
this.options = {};
|
|
this.locale = jsDate.regional.getLocale();
|
|
this.formatString = '';
|
|
this.defaultCentury = jsDate.config.defaultCentury;
|
|
|
|
switch ( arguments.length ) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
// other objects either won't have a _type property or,
|
|
// if they do, it shouldn't be set to "jsDate", so
|
|
// assume it is an options argument.
|
|
if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") {
|
|
var opts = this.options = arguments[0];
|
|
this.syntax = opts.syntax || this.syntax;
|
|
this.defaultCentury = opts.defaultCentury || this.defaultCentury;
|
|
this.proxy = jsDate.createDate(opts.date);
|
|
}
|
|
else {
|
|
this.proxy = jsDate.createDate(arguments[0]);
|
|
}
|
|
break;
|
|
default:
|
|
var a = [];
|
|
for ( var i=0; i<arguments.length; i++ ) {
|
|
a.push(arguments[i]);
|
|
}
|
|
// this should be the current date/time?
|
|
this.proxy = new Date();
|
|
this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) );
|
|
if ( a.slice(3).length ) {
|
|
this.proxy.setHours.apply( this.proxy, a.slice(3) );
|
|
}
|
|
break;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @namespace Configuration options that will be used as defaults for all instances on the page.
|
|
* @property {String} defaultLocale The default locale to use [en].
|
|
* @property {String} syntax The default syntax to use [perl].
|
|
* @property {Number} defaultCentury The default centry for 2 digit dates.
|
|
*/
|
|
jsDate.config = {
|
|
defaultLocale: 'en',
|
|
syntax: 'perl',
|
|
defaultCentury: 1900
|
|
};
|
|
|
|
/**
|
|
* Add an arbitrary amount to the currently stored date
|
|
*
|
|
* @param {Number} number
|
|
* @param {String} unit
|
|
* @returns {jsDate}
|
|
*/
|
|
|
|
jsDate.prototype.add = function(number, unit) {
|
|
var factor = multipliers[unit] || multipliers.day;
|
|
if (typeof factor == 'number') {
|
|
this.proxy.setTime(this.proxy.getTime() + (factor * number));
|
|
} else {
|
|
factor.add(this, number);
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Create a new jqplot.date object with the same date
|
|
*
|
|
* @returns {jsDate}
|
|
*/
|
|
|
|
jsDate.prototype.clone = function() {
|
|
return new jsDate(this.proxy.getTime());
|
|
};
|
|
|
|
/**
|
|
* Get the UTC TimeZone Offset of this date in milliseconds.
|
|
*
|
|
* @returns {Number}
|
|
*/
|
|
|
|
jsDate.prototype.getUtcOffset = function() {
|
|
return this.proxy.getTimezoneOffset() * 60000;
|
|
};
|
|
|
|
/**
|
|
* Find the difference between this jsDate and another date.
|
|
*
|
|
* @param {String| Number| Array| jsDate Object| Date Object} dateObj
|
|
* @param {String} unit
|
|
* @param {Boolean} allowDecimal
|
|
* @returns {Number} Number of units difference between dates.
|
|
*/
|
|
|
|
jsDate.prototype.diff = function(dateObj, unit, allowDecimal) {
|
|
// ensure we have a Date object
|
|
dateObj = new jsDate(dateObj);
|
|
if (dateObj === null) {
|
|
return null;
|
|
}
|
|
// get the multiplying factor integer or factor function
|
|
var factor = multipliers[unit] || multipliers.day;
|
|
if (typeof factor == 'number') {
|
|
// multiply
|
|
var unitDiff = (this.proxy.getTime() - dateObj.proxy.getTime()) / factor;
|
|
} else {
|
|
// run function
|
|
var unitDiff = factor.diff(this.proxy, dateObj.proxy);
|
|
}
|
|
// if decimals are not allowed, round toward zero
|
|
return (allowDecimal ? unitDiff : Math[unitDiff > 0 ? 'floor' : 'ceil'](unitDiff));
|
|
};
|
|
|
|
/**
|
|
* Get the abbreviated name of the current week day
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
|
|
jsDate.prototype.getAbbrDayName = function() {
|
|
return jsDate.regional[this.locale]["dayNamesShort"][this.proxy.getDay()];
|
|
};
|
|
|
|
/**
|
|
* Get the abbreviated name of the current month
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
|
|
jsDate.prototype.getAbbrMonthName = function() {
|
|
return jsDate.regional[this.locale]["monthNamesShort"][this.proxy.getMonth()];
|
|
};
|
|
|
|
/**
|
|
* Get UPPER CASE AM or PM for the current time
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
|
|
jsDate.prototype.getAMPM = function() {
|
|
return this.proxy.getHours() >= 12 ? 'PM' : 'AM';
|
|
};
|
|
|
|
/**
|
|
* Get lower case am or pm for the current time
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
|
|
jsDate.prototype.getAmPm = function() {
|
|
return this.proxy.getHours() >= 12 ? 'pm' : 'am';
|
|
};
|
|
|
|
/**
|
|
* Get the century (19 for 20th Century)
|
|
*
|
|
* @returns {Integer} Century (19 for 20th century).
|
|
*/
|
|
jsDate.prototype.getCentury = function() {
|
|
return parseInt(this.proxy.getFullYear()/100, 10);
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getDate = function() {
|
|
return this.proxy.getDate();
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getDay = function() {
|
|
return this.proxy.getDay();
|
|
};
|
|
|
|
/**
|
|
* Get the Day of week 1 (Monday) thru 7 (Sunday)
|
|
*
|
|
* @returns {Integer} Day of week 1 (Monday) thru 7 (Sunday)
|
|
*/
|
|
jsDate.prototype.getDayOfWeek = function() {
|
|
var dow = this.proxy.getDay();
|
|
return dow===0?7:dow;
|
|
};
|
|
|
|
/**
|
|
* Get the day of the year
|
|
*
|
|
* @returns {Integer} 1 - 366, day of the year
|
|
*/
|
|
jsDate.prototype.getDayOfYear = function() {
|
|
var d = this.proxy;
|
|
var ms = d - new Date('' + d.getFullYear() + '/1/1 GMT');
|
|
ms += d.getTimezoneOffset()*60000;
|
|
d = null;
|
|
return parseInt(ms/60000/60/24, 10)+1;
|
|
};
|
|
|
|
/**
|
|
* Get the name of the current week day
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
|
|
jsDate.prototype.getDayName = function() {
|
|
return jsDate.regional[this.locale]["dayNames"][this.proxy.getDay()];
|
|
};
|
|
|
|
/**
|
|
* Get the week number of the given year, starting with the first Sunday as the first week
|
|
* @returns {Integer} Week number (13 for the 13th full week of the year).
|
|
*/
|
|
jsDate.prototype.getFullWeekOfYear = function() {
|
|
var d = this.proxy;
|
|
var doy = this.getDayOfYear();
|
|
var rdow = 6-d.getDay();
|
|
var woy = parseInt((doy+rdow)/7, 10);
|
|
return woy;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getFullYear = function() {
|
|
return this.proxy.getFullYear();
|
|
};
|
|
|
|
/**
|
|
* Get the GMT offset in hours and minutes (e.g. +06:30)
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
|
|
jsDate.prototype.getGmtOffset = function() {
|
|
// divide the minutes offset by 60
|
|
var hours = this.proxy.getTimezoneOffset() / 60;
|
|
// decide if we are ahead of or behind GMT
|
|
var prefix = hours < 0 ? '+' : '-';
|
|
// remove the negative sign if any
|
|
hours = Math.abs(hours);
|
|
// add the +/- to the padded number of hours to : to the padded minutes
|
|
return prefix + addZeros(Math.floor(hours), 2) + ':' + addZeros((hours % 1) * 60, 2);
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getHours = function() {
|
|
return this.proxy.getHours();
|
|
};
|
|
|
|
/**
|
|
* Get the current hour on a 12-hour scheme
|
|
*
|
|
* @returns {Integer}
|
|
*/
|
|
|
|
jsDate.prototype.getHours12 = function() {
|
|
var hours = this.proxy.getHours();
|
|
return hours > 12 ? hours - 12 : (hours == 0 ? 12 : hours);
|
|
};
|
|
|
|
|
|
jsDate.prototype.getIsoWeek = function() {
|
|
var d = this.proxy;
|
|
var woy = this.getWeekOfYear();
|
|
var dow1_1 = (new Date('' + d.getFullYear() + '/1/1')).getDay();
|
|
// First week is 01 and not 00 as in the case of %U and %W,
|
|
// so we add 1 to the final result except if day 1 of the year
|
|
// is a Monday (then %W returns 01).
|
|
// We also need to subtract 1 if the day 1 of the year is
|
|
// Friday-Sunday, so the resulting equation becomes:
|
|
var idow = woy + (dow1_1 > 4 || dow1_1 <= 1 ? 0 : 1);
|
|
if(idow == 53 && (new Date('' + d.getFullYear() + '/12/31')).getDay() < 4)
|
|
{
|
|
idow = 1;
|
|
}
|
|
else if(idow === 0)
|
|
{
|
|
d = new jsDate(new Date('' + (d.getFullYear()-1) + '/12/31'));
|
|
idow = d.getIsoWeek();
|
|
}
|
|
d = null;
|
|
return idow;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getMilliseconds = function() {
|
|
return this.proxy.getMilliseconds();
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getMinutes = function() {
|
|
return this.proxy.getMinutes();
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getMonth = function() {
|
|
return this.proxy.getMonth();
|
|
};
|
|
|
|
/**
|
|
* Get the name of the current month
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
|
|
jsDate.prototype.getMonthName = function() {
|
|
return jsDate.regional[this.locale]["monthNames"][this.proxy.getMonth()];
|
|
};
|
|
|
|
/**
|
|
* Get the number of the current month, 1-12
|
|
*
|
|
* @returns {Integer}
|
|
*/
|
|
|
|
jsDate.prototype.getMonthNumber = function() {
|
|
return this.proxy.getMonth() + 1;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getSeconds = function() {
|
|
return this.proxy.getSeconds();
|
|
};
|
|
|
|
/**
|
|
* Return a proper two-digit year integer
|
|
*
|
|
* @returns {Integer}
|
|
*/
|
|
|
|
jsDate.prototype.getShortYear = function() {
|
|
return this.proxy.getYear() % 100;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getTime = function() {
|
|
return this.proxy.getTime();
|
|
};
|
|
|
|
/**
|
|
* Get the timezone abbreviation
|
|
*
|
|
* @returns {String} Abbreviation for the timezone
|
|
*/
|
|
jsDate.prototype.getTimezoneAbbr = function() {
|
|
return this.proxy.toString().replace(/^.*\(([^)]+)\)$/, '$1');
|
|
};
|
|
|
|
/**
|
|
* Get the browser-reported name for the current timezone (e.g. MDT, Mountain Daylight Time)
|
|
*
|
|
* @returns {String}
|
|
*/
|
|
jsDate.prototype.getTimezoneName = function() {
|
|
var match = /(?:\((.+)\)$| ([A-Z]{3}) )/.exec(this.toString());
|
|
return match[1] || match[2] || 'GMT' + this.getGmtOffset();
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getTimezoneOffset = function() {
|
|
return this.proxy.getTimezoneOffset();
|
|
};
|
|
|
|
|
|
/**
|
|
* Get the week number of the given year, starting with the first Monday as the first week
|
|
* @returns {Integer} Week number (13 for the 13th week of the year).
|
|
*/
|
|
jsDate.prototype.getWeekOfYear = function() {
|
|
var doy = this.getDayOfYear();
|
|
var rdow = 7 - this.getDayOfWeek();
|
|
var woy = parseInt((doy+rdow)/7, 10);
|
|
return woy;
|
|
};
|
|
|
|
/**
|
|
* Get the current date as a Unix timestamp
|
|
*
|
|
* @returns {Integer}
|
|
*/
|
|
|
|
jsDate.prototype.getUnix = function() {
|
|
return Math.round(this.proxy.getTime() / 1000, 0);
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.getYear = function() {
|
|
return this.proxy.getYear();
|
|
};
|
|
|
|
/**
|
|
* Return a date one day ahead (or any other unit)
|
|
*
|
|
* @param {String} unit Optional, year | month | day | week | hour | minute | second | millisecond
|
|
* @returns {jsDate}
|
|
*/
|
|
|
|
jsDate.prototype.next = function(unit) {
|
|
unit = unit || 'day';
|
|
return this.clone().add(1, unit);
|
|
};
|
|
|
|
/**
|
|
* Set the jsDate instance to a new date.
|
|
*
|
|
* @param {String | Number | Array | Date Object | jsDate Object | Options Object} arguments Optional arguments,
|
|
* either a parsable date/time string,
|
|
* a JavaScript timestamp, an array of numbers of form [year, month, day, hours, minutes, seconds, milliseconds],
|
|
* a Date object, jsDate Object or an options object of form {syntax: "perl", date:some Date} where all options are optional.
|
|
*/
|
|
jsDate.prototype.set = function() {
|
|
switch ( arguments.length ) {
|
|
case 0:
|
|
this.proxy = new Date();
|
|
break;
|
|
case 1:
|
|
// other objects either won't have a _type property or,
|
|
// if they do, it shouldn't be set to "jsDate", so
|
|
// assume it is an options argument.
|
|
if (get_type(arguments[0]) == "[object Object]" && arguments[0]._type != "jsDate") {
|
|
var opts = this.options = arguments[0];
|
|
this.syntax = opts.syntax || this.syntax;
|
|
this.defaultCentury = opts.defaultCentury || this.defaultCentury;
|
|
this.proxy = jsDate.createDate(opts.date);
|
|
}
|
|
else {
|
|
this.proxy = jsDate.createDate(arguments[0]);
|
|
}
|
|
break;
|
|
default:
|
|
var a = [];
|
|
for ( var i=0; i<arguments.length; i++ ) {
|
|
a.push(arguments[i]);
|
|
}
|
|
// this should be the current date/time
|
|
this.proxy = new Date();
|
|
this.proxy.setFullYear.apply( this.proxy, a.slice(0,3) );
|
|
if ( a.slice(3).length ) {
|
|
this.proxy.setHours.apply( this.proxy, a.slice(3) );
|
|
}
|
|
break;
|
|
}
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Sets the day of the month for a specified date according to local time.
|
|
* @param {Integer} dayValue An integer from 1 to 31, representing the day of the month.
|
|
*/
|
|
jsDate.prototype.setDate = function(n) {
|
|
this.proxy.setDate(n);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Sets the full year for a specified date according to local time.
|
|
* @param {Integer} yearValue The numeric value of the year, for example, 1995.
|
|
* @param {Integer} monthValue Optional, between 0 and 11 representing the months January through December.
|
|
* @param {Integer} dayValue Optional, between 1 and 31 representing the day of the month. If you specify the dayValue parameter, you must also specify the monthValue.
|
|
*/
|
|
jsDate.prototype.setFullYear = function() {
|
|
this.proxy.setFullYear.apply(this.proxy, arguments);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Sets the hours for a specified date according to local time.
|
|
*
|
|
* @param {Integer} hoursValue An integer between 0 and 23, representing the hour.
|
|
* @param {Integer} minutesValue Optional, An integer between 0 and 59, representing the minutes.
|
|
* @param {Integer} secondsValue Optional, An integer between 0 and 59, representing the seconds.
|
|
* If you specify the secondsValue parameter, you must also specify the minutesValue.
|
|
* @param {Integer} msValue Optional, A number between 0 and 999, representing the milliseconds.
|
|
* If you specify the msValue parameter, you must also specify the minutesValue and secondsValue.
|
|
*/
|
|
jsDate.prototype.setHours = function() {
|
|
this.proxy.setHours.apply(this.proxy, arguments);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.setMilliseconds = function(n) {
|
|
this.proxy.setMilliseconds(n);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.setMinutes = function() {
|
|
this.proxy.setMinutes.apply(this.proxy, arguments);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.setMonth = function() {
|
|
this.proxy.setMonth.apply(this.proxy, arguments);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.setSeconds = function() {
|
|
this.proxy.setSeconds.apply(this.proxy, arguments);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.setTime = function(n) {
|
|
this.proxy.setTime(n);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Implements Date functionality
|
|
*/
|
|
jsDate.prototype.setYear = function() {
|
|
this.proxy.setYear.apply(this.proxy, arguments);
|
|
return this;
|
|
};
|
|
|
|
/**
|
|
* Provide a formatted string representation of this date.
|
|
*
|
|
* @param {String} formatString A format string.
|
|
* See: {@link jsDate.formats}.
|
|
* @returns {String} Date String.
|
|
*/
|
|
|
|
jsDate.prototype.strftime = function(formatString) {
|
|
formatString = formatString || this.formatString || jsDate.regional[this.locale]['formatString'];
|
|
return jsDate.strftime(this, formatString, this.syntax);
|
|
};
|
|
|
|
/**
|
|
* Return a String representation of this jsDate object.
|
|
* @returns {String} Date string.
|
|
*/
|
|
|
|
jsDate.prototype.toString = function() {
|
|
return this.proxy.toString();
|
|
};
|
|
|
|
/**
|
|
* Convert the current date to an 8-digit integer (%Y%m%d)
|
|
*
|
|
* @returns {Integer}
|
|
*/
|
|
|
|
jsDate.prototype.toYmdInt = function() {
|
|
return (this.proxy.getFullYear() * 10000) + (this.getMonthNumber() * 100) + this.proxy.getDate();
|
|
};
|
|
|
|
/**
|
|
* @namespace Holds localizations for month/day names.
|
|
* <p>jsDate attempts to detect locale when loaded and defaults to 'en'.
|
|
* If a localization is detected which is not available, jsDate defaults to 'en'.
|
|
* Additional localizations can be added after jsDate loads. After adding a localization,
|
|
* call the jsDate.regional.getLocale() method. Currently, en, fr and de are defined.</p>
|
|
*
|
|
* <p>Localizations must be an object and have the following properties defined: monthNames, monthNamesShort, dayNames, dayNamesShort and Localizations are added like:</p>
|
|
* <pre class="code">
|
|
* jsDate.regional['en'] = {
|
|
* monthNames : 'January February March April May June July August September October November December'.split(' '),
|
|
* monthNamesShort : 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '),
|
|
* dayNames : 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '),
|
|
* dayNamesShort : 'Sun Mon Tue Wed Thu Fri Sat'.split(' ')
|
|
* };
|
|
* </pre>
|
|
* <p>After adding localizations, call <code>jsDate.regional.getLocale();</code> to update the locale setting with the
|
|
* new localizations.</p>
|
|
*/
|
|
|
|
jsDate.regional = {
|
|
'en': {
|
|
monthNames: ['January','February','March','April','May','June','July','August','September','October','November','December'],
|
|
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun','Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
|
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
|
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'fr': {
|
|
monthNames: ['Janvier','Février','Mars','Avril','Mai','Juin','Juillet','Août','Septembre','Octobre','Novembre','Décembre'],
|
|
monthNamesShort: ['Jan','Fév','Mar','Avr','Mai','Jun','Jul','Aoû','Sep','Oct','Nov','Déc'],
|
|
dayNames: ['Dimanche','Lundi','Mardi','Mercredi','Jeudi','Vendredi','Samedi'],
|
|
dayNamesShort: ['Dim','Lun','Mar','Mer','Jeu','Ven','Sam'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'de': {
|
|
monthNames: ['Januar','Februar','März','April','Mai','Juni','Juli','August','September','Oktober','November','Dezember'],
|
|
monthNamesShort: ['Jan','Feb','Mär','Apr','Mai','Jun','Jul','Aug','Sep','Okt','Nov','Dez'],
|
|
dayNames: ['Sonntag','Montag','Dienstag','Mittwoch','Donnerstag','Freitag','Samstag'],
|
|
dayNamesShort: ['So','Mo','Di','Mi','Do','Fr','Sa'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'es': {
|
|
monthNames: ['Enero','Febrero','Marzo','Abril','Mayo','Junio', 'Julio','Agosto','Septiembre','Octubre','Noviembre','Diciembre'],
|
|
monthNamesShort: ['Ene','Feb','Mar','Abr','May','Jun', 'Jul','Ago','Sep','Oct','Nov','Dic'],
|
|
dayNames: ['Domingo','Lunes','Martes','Miércoles','Jueves','Viernes','Sábado'],
|
|
dayNamesShort: ['Dom','Lun','Mar','Mié','Juv','Vie','Sáb'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'ru': {
|
|
monthNames: ['Январь','Февраль','Март','Апрель','Май','Июнь','Июль','Август','Сентябрь','Октябрь','Ноябрь','Декабрь'],
|
|
monthNamesShort: ['Янв','Фев','Мар','Апр','Май','Июн','Июл','Авг','Сен','Окт','Ноя','Дек'],
|
|
dayNames: ['воскресенье','понедельник','вторник','среда','четверг','пятница','суббота'],
|
|
dayNamesShort: ['вск','пнд','втр','срд','чтв','птн','сбт'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'ar': {
|
|
monthNames: ['كانون الثاني', 'شباط', 'آذار', 'نيسان', 'آذار', 'حزيران','تموز', 'آب', 'أيلول', 'تشرين الأول', 'تشرين الثاني', 'كانون الأول'],
|
|
monthNamesShort: ['1','2','3','4','5','6','7','8','9','10','11','12'],
|
|
dayNames: ['السبت', 'الأحد', 'الاثنين', 'الثلاثاء', 'الأربعاء', 'الخميس', 'الجمعة'],
|
|
dayNamesShort: ['سبت', 'أحد', 'اثنين', 'ثلاثاء', 'أربعاء', 'خميس', 'جمعة'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'pt': {
|
|
monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho','Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
|
|
monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'],
|
|
dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
|
|
dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'pt-BR': {
|
|
monthNames: ['Janeiro','Fevereiro','Março','Abril','Maio','Junho', 'Julho','Agosto','Setembro','Outubro','Novembro','Dezembro'],
|
|
monthNamesShort: ['Jan','Fev','Mar','Abr','Mai','Jun','Jul','Ago','Set','Out','Nov','Dez'],
|
|
dayNames: ['Domingo','Segunda-feira','Terça-feira','Quarta-feira','Quinta-feira','Sexta-feira','Sábado'],
|
|
dayNamesShort: ['Dom','Seg','Ter','Qua','Qui','Sex','Sáb'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'pl': {
|
|
monthNames: ['Styczeń','Luty','Marzec','Kwiecień','Maj','Czerwiec','Lipiec','Sierpień','Wrzesień','Październik','Listopad','Grudzień'],
|
|
monthNamesShort: ['Sty', 'Lut', 'Mar', 'Kwi', 'Maj', 'Cze','Lip', 'Sie', 'Wrz', 'Paź', 'Lis', 'Gru'],
|
|
dayNames: ['Niedziela', 'Poniedziałek', 'Wtorek', 'Środa', 'Czwartek', 'Piątek', 'Sobota'],
|
|
dayNamesShort: ['Ni', 'Pn', 'Wt', 'Śr', 'Cz', 'Pt', 'Sb'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'nl': {
|
|
monthNames: ['Januari','Februari','Maart','April','Mei','Juni','July','Augustus','September','Oktober','November','December'],
|
|
monthNamesShort: ['Jan','Feb','Mar','Apr','Mei','Jun','Jul','Aug','Sep','Okt','Nov','Dec'],
|
|
dayNames:','['Zondag','Maandag','Dinsdag','Woensdag','Donderdag','Vrijdag','Zaterdag'],
|
|
dayNamesShort: ['Zo','Ma','Di','Wo','Do','Vr','Za'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
},
|
|
|
|
'sv': {
|
|
monthNames: ['januari','februari','mars','april','maj','juni','juli','augusti','september','oktober','november','december'],
|
|
monthNamesShort: ['jan','feb','mar','apr','maj','jun','jul','aug','sep','okt','nov','dec'],
|
|
dayNames: ['söndag','måndag','tisdag','onsdag','torsdag','fredag','lördag'],
|
|
dayNamesShort: ['sön','mån','tis','ons','tor','fre','lör'],
|
|
formatString: '%Y-%m-%d %H:%M:%S'
|
|
}
|
|
|
|
};
|
|
|
|
// Set english variants to 'en'
|
|
jsDate.regional['en-US'] = jsDate.regional['en-GB'] = jsDate.regional['en'];
|
|
|
|
/**
|
|
* Try to determine the users locale based on the lang attribute of the html page. Defaults to 'en'
|
|
* if it cannot figure out a locale of if the locale does not have a localization defined.
|
|
* @returns {String} locale
|
|
*/
|
|
|
|
jsDate.regional.getLocale = function () {
|
|
var l = jsDate.config.defaultLocale;
|
|
|
|
if ( document && document.getElementsByTagName('html') && document.getElementsByTagName('html')[0].lang ) {
|
|
l = document.getElementsByTagName('html')[0].lang;
|
|
if (!jsDate.regional.hasOwnProperty(l)) {
|
|
l = jsDate.config.defaultLocale;
|
|
}
|
|
}
|
|
|
|
return l;
|
|
};
|
|
|
|
// ms in day
|
|
var day = 24 * 60 * 60 * 1000;
|
|
|
|
// padd a number with zeros
|
|
var addZeros = function(num, digits) {
|
|
num = String(num);
|
|
var i = digits - num.length;
|
|
var s = String(Math.pow(10, i)).slice(1);
|
|
return s.concat(num);
|
|
};
|
|
|
|
// representations used for calculating differences between dates.
|
|
// This borrows heavily from Ken Snyder's work.
|
|
var multipliers = {
|
|
millisecond: 1,
|
|
second: 1000,
|
|
minute: 60 * 1000,
|
|
hour: 60 * 60 * 1000,
|
|
day: day,
|
|
week: 7 * day,
|
|
month: {
|
|
// add a number of months
|
|
add: function(d, number) {
|
|
// add any years needed (increments of 12)
|
|
multipliers.year.add(d, Math[number > 0 ? 'floor' : 'ceil'](number / 12));
|
|
// ensure that we properly wrap betwen December and January
|
|
// 11 % 12 = 11
|
|
// 12 % 12 = 0
|
|
var prevMonth = d.getMonth() + (number % 12);
|
|
if (prevMonth == 12) {
|
|
prevMonth = 0;
|
|
d.setYear(d.getFullYear() + 1);
|
|
} else if (prevMonth == -1) {
|
|
prevMonth = 11;
|
|
d.setYear(d.getFullYear() - 1);
|
|
}
|
|
d.setMonth(prevMonth);
|
|
},
|
|
// get the number of months between two Date objects (decimal to the nearest day)
|
|
diff: function(d1, d2) {
|
|
// get the number of years
|
|
var diffYears = d1.getFullYear() - d2.getFullYear();
|
|
// get the number of remaining months
|
|
var diffMonths = d1.getMonth() - d2.getMonth() + (diffYears * 12);
|
|
// get the number of remaining days
|
|
var diffDays = d1.getDate() - d2.getDate();
|
|
// return the month difference with the days difference as a decimal
|
|
return diffMonths + (diffDays / 30);
|
|
}
|
|
},
|
|
year: {
|
|
// add a number of years
|
|
add: function(d, number) {
|
|
d.setYear(d.getFullYear() + Math[number > 0 ? 'floor' : 'ceil'](number));
|
|
},
|
|
// get the number of years between two Date objects (decimal to the nearest day)
|
|
diff: function(d1, d2) {
|
|
return multipliers.month.diff(d1, d2) / 12;
|
|
}
|
|
}
|
|
};
|
|
//
|
|
// Alias each multiplier with an 's' to allow 'year' and 'years' for example.
|
|
// This comes from Ken Snyders work.
|
|
//
|
|
for (var unit in multipliers) {
|
|
if (unit.substring(unit.length - 1) != 's') { // IE will iterate newly added properties :|
|
|
multipliers[unit + 's'] = multipliers[unit];
|
|
}
|
|
}
|
|
|
|
//
|
|
// take a jsDate instance and a format code and return the formatted value.
|
|
// This is a somewhat modified version of Ken Snyder's method.
|
|
//
|
|
var format = function(d, code, syntax) {
|
|
// if shorcut codes are used, recursively expand those.
|
|
if (jsDate.formats[syntax]["shortcuts"][code]) {
|
|
return jsDate.strftime(d, jsDate.formats[syntax]["shortcuts"][code], syntax);
|
|
} else {
|
|
// get the format code function and addZeros() argument
|
|
var getter = (jsDate.formats[syntax]["codes"][code] || '').split('.');
|
|
var nbr = d['get' + getter[0]] ? d['get' + getter[0]]() : '';
|
|
if (getter[1]) {
|
|
nbr = addZeros(nbr, getter[1]);
|
|
}
|
|
return nbr;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* @static
|
|
* Static function for convert a date to a string according to a given format. Also acts as namespace for strftime format codes.
|
|
* <p>strftime formatting can be accomplished without creating a jsDate object by calling jsDate.strftime():</p>
|
|
* <pre class="code">
|
|
* var formattedDate = jsDate.strftime('Feb 8, 2006 8:48:32', '%Y-%m-%d %H:%M:%S');
|
|
* </pre>
|
|
* @param {String | Number | Array | jsDate Object | Date Object} date A parsable date string, JavaScript time stamp, Array of form [year, month, day, hours, minutes, seconds, milliseconds], jsDate Object or Date object.
|
|
* @param {String} formatString String with embedded date formatting codes.
|
|
* See: {@link jsDate.formats}.
|
|
* @param {String} syntax Optional syntax to use [default perl].
|
|
* @param {String} locale Optional locale to use.
|
|
* @returns {String} Formatted representation of the date.
|
|
*/
|
|
//
|
|
// Logic as implemented here is very similar to Ken Snyder's Date Instance Methods.
|
|
//
|
|
jsDate.strftime = function(d, formatString, syntax, locale) {
|
|
var syn = 'perl';
|
|
var loc = jsDate.regional.getLocale();
|
|
|
|
// check if syntax and locale are available or reversed
|
|
if (syntax && jsDate.formats.hasOwnProperty(syntax)) {
|
|
syn = syntax;
|
|
}
|
|
else if (syntax && jsDate.regional.hasOwnProperty(syntax)) {
|
|
loc = syntax;
|
|
}
|
|
|
|
if (locale && jsDate.formats.hasOwnProperty(locale)) {
|
|
syn = locale;
|
|
}
|
|
else if (locale && jsDate.regional.hasOwnProperty(locale)) {
|
|
loc = locale;
|
|
}
|
|
|
|
if (get_type(d) != "[object Object]" || d._type != "jsDate") {
|
|
d = new jsDate(d);
|
|
d.locale = loc;
|
|
}
|
|
if (!formatString) {
|
|
formatString = d.formatString || jsDate.regional[loc]['formatString'];
|
|
}
|
|
// default the format string to year-month-day
|
|
var source = formatString || '%Y-%m-%d',
|
|
result = '',
|
|
match;
|
|
// replace each format code
|
|
while (source.length > 0) {
|
|
if (match = source.match(jsDate.formats[syn].codes.matcher)) {
|
|
result += source.slice(0, match.index);
|
|
result += (match[1] || '') + format(d, match[2], syn);
|
|
source = source.slice(match.index + match[0].length);
|
|
} else {
|
|
result += source;
|
|
source = '';
|
|
}
|
|
}
|
|
return result;
|
|
};
|
|
|
|
/**
|
|
* @namespace
|
|
* Namespace to hold format codes and format shortcuts. "perl" and "php" format codes
|
|
* and shortcuts are defined by default. Additional codes and shortcuts can be
|
|
* added like:
|
|
*
|
|
* <pre class="code">
|
|
* jsDate.formats["perl"] = {
|
|
* "codes": {
|
|
* matcher: /someregex/,
|
|
* Y: "fullYear", // name of "get" method without the "get",
|
|
* ..., // more codes
|
|
* },
|
|
* "shortcuts": {
|
|
* F: '%Y-%m-%d',
|
|
* ..., // more shortcuts
|
|
* }
|
|
* };
|
|
* </pre>
|
|
*
|
|
* <p>Additionally, ISO and SQL shortcuts are defined and can be accesses via:
|
|
* <code>jsDate.formats.ISO</code> and <code>jsDate.formats.SQL</code>
|
|
*/
|
|
|
|
jsDate.formats = {
|
|
ISO:'%Y-%m-%dT%H:%M:%S.%N%G',
|
|
SQL:'%Y-%m-%d %H:%M:%S'
|
|
};
|
|
|
|
/**
|
|
* Perl format codes and shortcuts for strftime.
|
|
*
|
|
* A hash (object) of codes where each code must be an array where the first member is
|
|
* the name of a Date.prototype or jsDate.prototype function to call
|
|
* and optionally a second member indicating the number to pass to addZeros()
|
|
*
|
|
* <p>The following format codes are defined:</p>
|
|
*
|
|
* <pre class="code">
|
|
* Code Result Description
|
|
* == Years ==
|
|
* %Y 2008 Four-digit year
|
|
* %y 08 Two-digit year
|
|
*
|
|
* == Months ==
|
|
* %m 09 Two-digit month
|
|
* %#m 9 One or two-digit month
|
|
* %B September Full month name
|
|
* %b Sep Abbreviated month name
|
|
*
|
|
* == Days ==
|
|
* %d 05 Two-digit day of month
|
|
* %#d 5 One or two-digit day of month
|
|
* %e 5 One or two-digit day of month
|
|
* %A Sunday Full name of the day of the week
|
|
* %a Sun Abbreviated name of the day of the week
|
|
* %w 0 Number of the day of the week (0 = Sunday, 6 = Saturday)
|
|
*
|
|
* == Hours ==
|
|
* %H 23 Hours in 24-hour format (two digits)
|
|
* %#H 3 Hours in 24-hour integer format (one or two digits)
|
|
* %I 11 Hours in 12-hour format (two digits)
|
|
* %#I 3 Hours in 12-hour integer format (one or two digits)
|
|
* %p PM AM or PM
|
|
*
|
|
* == Minutes ==
|
|
* %M 09 Minutes (two digits)
|
|
* %#M 9 Minutes (one or two digits)
|
|
*
|
|
* == Seconds ==
|
|
* %S 02 Seconds (two digits)
|
|
* %#S 2 Seconds (one or two digits)
|
|
* %s 1206567625723 Unix timestamp (Seconds past 1970-01-01 00:00:00)
|
|
*
|
|
* == Milliseconds ==
|
|
* %N 008 Milliseconds (three digits)
|
|
* %#N 8 Milliseconds (one to three digits)
|
|
*
|
|
* == Timezone ==
|
|
* %O 360 difference in minutes between local time and GMT
|
|
* %Z Mountain Standard Time Name of timezone as reported by browser
|
|
* %G 06:00 Hours and minutes between GMT
|
|
*
|
|
* == Shortcuts ==
|
|
* %F 2008-03-26 %Y-%m-%d
|
|
* %T 05:06:30 %H:%M:%S
|
|
* %X 05:06:30 %H:%M:%S
|
|
* %x 03/26/08 %m/%d/%y
|
|
* %D 03/26/08 %m/%d/%y
|
|
* %#c Wed Mar 26 15:31:00 2008 %a %b %e %H:%M:%S %Y
|
|
* %v 3-Sep-2008 %e-%b-%Y
|
|
* %R 15:31 %H:%M
|
|
* %r 03:31:00 PM %I:%M:%S %p
|
|
*
|
|
* == Characters ==
|
|
* %n \n Newline
|
|
* %t \t Tab
|
|
* %% % Percent Symbol
|
|
* </pre>
|
|
*
|
|
* <p>Formatting shortcuts that will be translated into their longer version.
|
|
* Be sure that format shortcuts do not refer to themselves: this will cause an infinite loop.</p>
|
|
*
|
|
* <p>Format codes and format shortcuts can be redefined after the jsDate
|
|
* module is imported.</p>
|
|
*
|
|
* <p>Note that if you redefine the whole hash (object), you must supply a "matcher"
|
|
* regex for the parser. The default matcher is:</p>
|
|
*
|
|
* <code>/()%(#?(%|[a-z]))/i</code>
|
|
*
|
|
* <p>which corresponds to the Perl syntax used by default.</p>
|
|
*
|
|
* <p>By customizing the matcher and format codes, nearly any strftime functionality is possible.</p>
|
|
*/
|
|
|
|
jsDate.formats.perl = {
|
|
codes: {
|
|
//
|
|
// 2-part regex matcher for format codes
|
|
//
|
|
// first match must be the character before the code (to account for escaping)
|
|
// second match must be the format code character(s)
|
|
//
|
|
matcher: /()%(#?(%|[a-z]))/i,
|
|
// year
|
|
Y: 'FullYear',
|
|
y: 'ShortYear.2',
|
|
// month
|
|
m: 'MonthNumber.2',
|
|
'#m': 'MonthNumber',
|
|
B: 'MonthName',
|
|
b: 'AbbrMonthName',
|
|
// day
|
|
d: 'Date.2',
|
|
'#d': 'Date',
|
|
e: 'Date',
|
|
A: 'DayName',
|
|
a: 'AbbrDayName',
|
|
w: 'Day',
|
|
// hours
|
|
H: 'Hours.2',
|
|
'#H': 'Hours',
|
|
I: 'Hours12.2',
|
|
'#I': 'Hours12',
|
|
p: 'AMPM',
|
|
// minutes
|
|
M: 'Minutes.2',
|
|
'#M': 'Minutes',
|
|
// seconds
|
|
S: 'Seconds.2',
|
|
'#S': 'Seconds',
|
|
s: 'Unix',
|
|
// milliseconds
|
|
N: 'Milliseconds.3',
|
|
'#N': 'Milliseconds',
|
|
// timezone
|
|
O: 'TimezoneOffset',
|
|
Z: 'TimezoneName',
|
|
G: 'GmtOffset'
|
|
},
|
|
|
|
shortcuts: {
|
|
// date
|
|
F: '%Y-%m-%d',
|
|
// time
|
|
T: '%H:%M:%S',
|
|
X: '%H:%M:%S',
|
|
// local format date
|
|
x: '%m/%d/%y',
|
|
D: '%m/%d/%y',
|
|
// local format extended
|
|
'#c': '%a %b %e %H:%M:%S %Y',
|
|
// local format short
|
|
v: '%e-%b-%Y',
|
|
R: '%H:%M',
|
|
r: '%I:%M:%S %p',
|
|
// tab and newline
|
|
t: '\t',
|
|
n: '\n',
|
|
'%': '%'
|
|
}
|
|
};
|
|
|
|
/**
|
|
* PHP format codes and shortcuts for strftime.
|
|
*
|
|
* A hash (object) of codes where each code must be an array where the first member is
|
|
* the name of a Date.prototype or jsDate.prototype function to call
|
|
* and optionally a second member indicating the number to pass to addZeros()
|
|
*
|
|
* <p>The following format codes are defined:</p>
|
|
*
|
|
* <pre class="code">
|
|
* Code Result Description
|
|
* === Days ===
|
|
* %a Sun through Sat An abbreviated textual representation of the day
|
|
* %A Sunday - Saturday A full textual representation of the day
|
|
* %d 01 to 31 Two-digit day of the month (with leading zeros)
|
|
* %e 1 to 31 Day of the month, with a space preceding single digits.
|
|
* %j 001 to 366 Day of the year, 3 digits with leading zeros
|
|
* %u 1 - 7 (Mon - Sun) ISO-8601 numeric representation of the day of the week
|
|
* %w 0 - 6 (Sun - Sat) Numeric representation of the day of the week
|
|
*
|
|
* === Week ===
|
|
* %U 13 Full Week number, starting with the first Sunday as the first week
|
|
* %V 01 through 53 ISO-8601:1988 week number, starting with the first week of the year
|
|
* with at least 4 weekdays, with Monday being the start of the week
|
|
* %W 46 A numeric representation of the week of the year,
|
|
* starting with the first Monday as the first week
|
|
* === Month ===
|
|
* %b Jan through Dec Abbreviated month name, based on the locale
|
|
* %B January - December Full month name, based on the locale
|
|
* %h Jan through Dec Abbreviated month name, based on the locale (an alias of %b)
|
|
* %m 01 - 12 (Jan - Dec) Two digit representation of the month
|
|
*
|
|
* === Year ===
|
|
* %C 19 Two digit century (year/100, truncated to an integer)
|
|
* %y 09 for 2009 Two digit year
|
|
* %Y 2038 Four digit year
|
|
*
|
|
* === Time ===
|
|
* %H 00 through 23 Two digit representation of the hour in 24-hour format
|
|
* %I 01 through 12 Two digit representation of the hour in 12-hour format
|
|
* %l 1 through 12 Hour in 12-hour format, with a space preceeding single digits
|
|
* %M 00 through 59 Two digit representation of the minute
|
|
* %p AM/PM UPPER-CASE 'AM' or 'PM' based on the given time
|
|
* %P am/pm lower-case 'am' or 'pm' based on the given time
|
|
* %r 09:34:17 PM Same as %I:%M:%S %p
|
|
* %R 00:35 Same as %H:%M
|
|
* %S 00 through 59 Two digit representation of the second
|
|
* %T 21:34:17 Same as %H:%M:%S
|
|
* %X 03:59:16 Preferred time representation based on locale, without the date
|
|
* %z -0500 or EST Either the time zone offset from UTC or the abbreviation
|
|
* %Z -0500 or EST The time zone offset/abbreviation option NOT given by %z
|
|
*
|
|
* === Time and Date ===
|
|
* %D 02/05/09 Same as %m/%d/%y
|
|
* %F 2009-02-05 Same as %Y-%m-%d (commonly used in database datestamps)
|
|
* %s 305815200 Unix Epoch Time timestamp (same as the time() function)
|
|
* %x 02/05/09 Preferred date representation, without the time
|
|
*
|
|
* === Miscellaneous ===
|
|
* %n --- A newline character (\n)
|
|
* %t --- A Tab character (\t)
|
|
* %% --- A literal percentage character (%)
|
|
* </pre>
|
|
*/
|
|
|
|
jsDate.formats.php = {
|
|
codes: {
|
|
//
|
|
// 2-part regex matcher for format codes
|
|
//
|
|
// first match must be the character before the code (to account for escaping)
|
|
// second match must be the format code character(s)
|
|
//
|
|
matcher: /()%((%|[a-z]))/i,
|
|
// day
|
|
a: 'AbbrDayName',
|
|
A: 'DayName',
|
|
d: 'Date.2',
|
|
e: 'Date',
|
|
j: 'DayOfYear.3',
|
|
u: 'DayOfWeek',
|
|
w: 'Day',
|
|
// week
|
|
U: 'FullWeekOfYear.2',
|
|
V: 'IsoWeek.2',
|
|
W: 'WeekOfYear.2',
|
|
// month
|
|
b: 'AbbrMonthName',
|
|
B: 'MonthName',
|
|
m: 'MonthNumber.2',
|
|
h: 'AbbrMonthName',
|
|
// year
|
|
C: 'Century.2',
|
|
y: 'ShortYear.2',
|
|
Y: 'FullYear',
|
|
// time
|
|
H: 'Hours.2',
|
|
I: 'Hours12.2',
|
|
l: 'Hours12',
|
|
p: 'AMPM',
|
|
P: 'AmPm',
|
|
M: 'Minutes.2',
|
|
S: 'Seconds.2',
|
|
s: 'Unix',
|
|
O: 'TimezoneOffset',
|
|
z: 'GmtOffset',
|
|
Z: 'TimezoneAbbr'
|
|
},
|
|
|
|
shortcuts: {
|
|
D: '%m/%d/%y',
|
|
F: '%Y-%m-%d',
|
|
T: '%H:%M:%S',
|
|
X: '%H:%M:%S',
|
|
x: '%m/%d/%y',
|
|
R: '%H:%M',
|
|
r: '%I:%M:%S %p',
|
|
t: '\t',
|
|
n: '\n',
|
|
'%': '%'
|
|
}
|
|
};
|
|
//
|
|
// Conceptually, the logic implemented here is similar to Ken Snyder's Date Instance Methods.
|
|
// I use his idea of a set of parsers which can be regular expressions or functions,
|
|
// iterating through those, and then seeing if Date.parse() will create a date.
|
|
// The parser expressions and functions are a little different and some bugs have been
|
|
// worked out. Also, a lot of "pre-parsing" is done to fix implementation
|
|
// variations of Date.parse() between browsers.
|
|
//
|
|
jsDate.createDate = function(date) {
|
|
// if passing in multiple arguments, try Date constructor
|
|
if (date == null) {
|
|
return new Date();
|
|
}
|
|
// If the passed value is already a date object, return it
|
|
if (date instanceof Date) {
|
|
return date;
|
|
}
|
|
// if (typeof date == 'number') return new Date(date * 1000);
|
|
// If the passed value is an integer, interpret it as a javascript timestamp
|
|
if (typeof date == 'number') {
|
|
return new Date(date);
|
|
}
|
|
|
|
// Before passing strings into Date.parse(), have to normalize them for certain conditions.
|
|
// If strings are not formatted staccording to the EcmaScript spec, results from Date parse will be implementation dependent.
|
|
//
|
|
// For example:
|
|
// * FF and Opera assume 2 digit dates are pre y2k, Chome assumes <50 is pre y2k, 50+ is 21st century.
|
|
// * Chrome will correctly parse '1984-1-25' into localtime, FF and Opera will not parse.
|
|
// * Both FF, Chrome and Opera will parse '1984/1/25' into localtime.
|
|
|
|
// remove leading and trailing spaces
|
|
var parsable = String(date).replace(/^\s*(.+)\s*$/g, '$1');
|
|
|
|
// replace dahses (-) with slashes (/) in dates like n[nnn]/n[n]/n[nnn]
|
|
parsable = parsable.replace(/^([0-9]{1,4})-([0-9]{1,2})-([0-9]{1,4})/, "$1/$2/$3");
|
|
|
|
/////////
|
|
// Need to check for '15-Dec-09' also.
|
|
// FF will not parse, but Chrome will.
|
|
// Chrome will set date to 2009 as well.
|
|
/////////
|
|
|
|
// first check for 'dd-mmm-yyyy' or 'dd/mmm/yyyy' like '15-Dec-2010'
|
|
parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{4})/i, "$1 $2 $3");
|
|
|
|
// Now check for 'dd-mmm-yy' or 'dd/mmm/yy' and normalize years to default century.
|
|
var match = parsable.match(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i);
|
|
if (match && match.length > 3) {
|
|
var m3 = parseFloat(match[3]);
|
|
var ny = jsDate.config.defaultCentury + m3;
|
|
ny = String(ny);
|
|
|
|
// now replace 2 digit year with 4 digit year
|
|
parsable = parsable.replace(/^(3[01]|[0-2]?\d)[-\/]([a-z]{3,})[-\/](\d{2})\D*/i, match[1] +' '+ match[2] +' '+ ny);
|
|
|
|
}
|
|
|
|
// Check for '1/19/70 8:14PM'
|
|
// where starts with mm/dd/yy or yy/mm/dd and have something after
|
|
// Check if 1st postiion is greater than 31, assume it is year.
|
|
// Assme all 2 digit years are 1900's.
|
|
// Finally, change them into US style mm/dd/yyyy representations.
|
|
match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})[^0-9]/);
|
|
|
|
function h1(parsable, match) {
|
|
var m1 = parseFloat(match[1]);
|
|
var m2 = parseFloat(match[2]);
|
|
var m3 = parseFloat(match[3]);
|
|
var cent = jsDate.config.defaultCentury;
|
|
var ny, nd, nm, str;
|
|
|
|
if (m1 > 31) { // first number is a year
|
|
nd = m3;
|
|
nm = m2;
|
|
ny = cent + m1;
|
|
}
|
|
|
|
else { // last number is the year
|
|
nd = m2;
|
|
nm = m1;
|
|
ny = cent + m3;
|
|
}
|
|
|
|
str = nm+'/'+nd+'/'+ny;
|
|
|
|
// now replace 2 digit year with 4 digit year
|
|
return parsable.replace(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})/, str);
|
|
|
|
}
|
|
|
|
if (match && match.length > 3) {
|
|
parsable = h1(parsable, match);
|
|
}
|
|
|
|
// Now check for '1/19/70' with nothing after and do as above
|
|
var match = parsable.match(/^([0-9]{1,2})[-\/]([0-9]{1,2})[-\/]([0-9]{1,2})$/);
|
|
|
|
if (match && match.length > 3) {
|
|
parsable = h1(parsable, match);
|
|
}
|
|
|
|
|
|
var i = 0;
|
|
var length = jsDate.matchers.length;
|
|
var pattern,
|
|
ms,
|
|
current = parsable,
|
|
obj;
|
|
while (i < length) {
|
|
ms = Date.parse(current);
|
|
if (!isNaN(ms)) {
|
|
return new Date(ms);
|
|
}
|
|
pattern = jsDate.matchers[i];
|
|
if (typeof pattern == 'function') {
|
|
obj = pattern.call(jsDate, current);
|
|
if (obj instanceof Date) {
|
|
return obj;
|
|
}
|
|
} else {
|
|
current = parsable.replace(pattern[0], pattern[1]);
|
|
}
|
|
i++;
|
|
}
|
|
return NaN;
|
|
};
|
|
|
|
|
|
/**
|
|
* @static
|
|
* Handy static utility function to return the number of days in a given month.
|
|
* @param {Integer} year Year
|
|
* @param {Integer} month Month (1-12)
|
|
* @returns {Integer} Number of days in the month.
|
|
*/
|
|
//
|
|
// handy utility method Borrowed right from Ken Snyder's Date Instance Mehtods.
|
|
//
|
|
jsDate.daysInMonth = function(year, month) {
|
|
if (month == 2) {
|
|
return new Date(year, 1, 29).getDate() == 29 ? 29 : 28;
|
|
}
|
|
return [undefined,31,undefined,31,30,31,30,31,31,30,31,30,31][month];
|
|
};
|
|
|
|
|
|
//
|
|
// An Array of regular expressions or functions that will attempt to match the date string.
|
|
// Functions are called with scope of a jsDate instance.
|
|
//
|
|
jsDate.matchers = [
|
|
// convert dd.mmm.yyyy to mm/dd/yyyy (world date to US date).
|
|
[/(3[01]|[0-2]\d)\s*\.\s*(1[0-2]|0\d)\s*\.\s*([1-9]\d{3})/, '$2/$1/$3'],
|
|
// convert yyyy-mm-dd to mm/dd/yyyy (ISO date to US date).
|
|
[/([1-9]\d{3})\s*-\s*(1[0-2]|0\d)\s*-\s*(3[01]|[0-2]\d)/, '$2/$3/$1'],
|
|
// Handle 12 hour or 24 hour time with milliseconds am/pm and optional date part.
|
|
function(str) {
|
|
var match = str.match(/^(?:(.+)\s+)?([012]?\d)(?:\s*\:\s*(\d\d))?(?:\s*\:\s*(\d\d(\.\d*)?))?\s*(am|pm)?\s*$/i);
|
|
// opt. date hour opt. minute opt. second opt. msec opt. am or pm
|
|
if (match) {
|
|
if (match[1]) {
|
|
var d = this.createDate(match[1]);
|
|
if (isNaN(d)) {
|
|
return;
|
|
}
|
|
} else {
|
|
var d = new Date();
|
|
d.setMilliseconds(0);
|
|
}
|
|
var hour = parseFloat(match[2]);
|
|
if (match[6]) {
|
|
hour = match[6].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12);
|
|
}
|
|
d.setHours(hour, parseInt(match[3] || 0, 10), parseInt(match[4] || 0, 10), ((parseFloat(match[5] || 0)) || 0)*1000);
|
|
return d;
|
|
}
|
|
else {
|
|
return str;
|
|
}
|
|
},
|
|
// Handle ISO timestamp with time zone.
|
|
function(str) {
|
|
var match = str.match(/^(?:(.+))[T|\s+]([012]\d)(?:\:(\d\d))(?:\:(\d\d))(?:\.\d+)([\+\-]\d\d\:\d\d)$/i);
|
|
if (match) {
|
|
if (match[1]) {
|
|
var d = this.createDate(match[1]);
|
|
if (isNaN(d)) {
|
|
return;
|
|
}
|
|
} else {
|
|
var d = new Date();
|
|
d.setMilliseconds(0);
|
|
}
|
|
var hour = parseFloat(match[2]);
|
|
d.setHours(hour, parseInt(match[3], 10), parseInt(match[4], 10), parseFloat(match[5])*1000);
|
|
return d;
|
|
}
|
|
else {
|
|
return str;
|
|
}
|
|
},
|
|
// Try to match ambiguous strings like 12/8/22.
|
|
// Use FF date assumption that 2 digit years are 20th century (i.e. 1900's).
|
|
// This may be redundant with pre processing of date already performed.
|
|
function(str) {
|
|
var match = str.match(/^([0-3]?\d)\s*[-\/.\s]{1}\s*([a-zA-Z]{3,9})\s*[-\/.\s]{1}\s*([0-3]?\d)$/);
|
|
if (match) {
|
|
var d = new Date();
|
|
var cent = jsDate.config.defaultCentury;
|
|
var m1 = parseFloat(match[1]);
|
|
var m3 = parseFloat(match[3]);
|
|
var ny, nd, nm;
|
|
if (m1 > 31) { // first number is a year
|
|
nd = m3;
|
|
ny = cent + m1;
|
|
}
|
|
|
|
else { // last number is the year
|
|
nd = m1;
|
|
ny = cent + m3;
|
|
}
|
|
|
|
var nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()]["monthNamesShort"]);
|
|
|
|
if (nm == -1) {
|
|
nm = inArray(match[2], jsDate.regional[jsDate.regional.getLocale()]["monthNames"]);
|
|
}
|
|
|
|
d.setFullYear(ny, nm, nd);
|
|
d.setHours(0,0,0,0);
|
|
return d;
|
|
}
|
|
|
|
else {
|
|
return str;
|
|
}
|
|
}
|
|
];
|
|
|
|
//
|
|
// I think John Reisig published this method on his blog, ejohn.
|
|
//
|
|
function inArray( elem, array ) {
|
|
if ( array.indexOf ) {
|
|
return array.indexOf( elem );
|
|
}
|
|
|
|
for ( var i = 0, length = array.length; i < length; i++ ) {
|
|
if ( array[ i ] === elem ) {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
//
|
|
// Thanks to Kangax, Christian Sciberras and Stack Overflow for this method.
|
|
//
|
|
function get_type(thing){
|
|
if(thing===null) return "[object Null]"; // special case
|
|
return Object.prototype.toString.call(thing);
|
|
}
|
|
|
|
$.jsDate = jsDate;
|
|
|
|
})(jQuery); |