mirror of
http://git.whoc.org.uk/git/password-manager.git
synced 2025-10-24 17:27:35 +02:00
Merged all pending work done on the private repository
This commit is contained in:
859
frontend/delta/js/xDate/xdate.js
Normal file
859
frontend/delta/js/xDate/xdate.js
Normal file
@@ -0,0 +1,859 @@
|
||||
/*
|
||||
|
||||
Copyright 2008-2015 Clipperz Srl
|
||||
|
||||
This file is part of Clipperz, the online password manager.
|
||||
For further information about its features and functionalities please
|
||||
refer to http://www.clipperz.com.
|
||||
|
||||
* Clipperz is free software: you can redistribute it and/or modify it
|
||||
under the terms of the GNU Affero General Public License as published
|
||||
by the Free Software Foundation, either version 3 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
* Clipperz 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 Affero General Public License for more details.
|
||||
|
||||
* You should have received a copy of the GNU Affero General Public
|
||||
License along with Clipperz. If not, see http://www.gnu.org/licenses/.
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @preserve XDate v@VERSION
|
||||
* Docs & Licensing: http://arshaw.com/xdate/
|
||||
*/
|
||||
|
||||
/*
|
||||
* Internal Architecture
|
||||
* ---------------------
|
||||
* An XDate wraps a native Date. The native Date is stored in the '0' property of the object.
|
||||
* UTC-mode is determined by whether the internal native Date's toString method is set to
|
||||
* Date.prototype.toUTCString (see getUTCMode).
|
||||
*
|
||||
*/
|
||||
|
||||
var XDate = (function(Date, Math, Array, undefined) {
|
||||
|
||||
|
||||
/** @const */ var FULLYEAR = 0;
|
||||
/** @const */ var MONTH = 1;
|
||||
/** @const */ var DATE = 2;
|
||||
/** @const */ var HOURS = 3;
|
||||
/** @const */ var MINUTES = 4;
|
||||
/** @const */ var SECONDS = 5;
|
||||
/** @const */ var MILLISECONDS = 6;
|
||||
/** @const */ var DAY = 7;
|
||||
/** @const */ var YEAR = 8;
|
||||
/** @const */ var WEEK = 9;
|
||||
/** @const */ var DAY_MS = 86400000;
|
||||
var ISO_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss(.fff)";
|
||||
var ISO_FORMAT_STRING_TZ = ISO_FORMAT_STRING + "zzz";
|
||||
|
||||
|
||||
var methodSubjects = [
|
||||
'FullYear', // 0
|
||||
'Month', // 1
|
||||
'Date', // 2
|
||||
'Hours', // 3
|
||||
'Minutes', // 4
|
||||
'Seconds', // 5
|
||||
'Milliseconds', // 6
|
||||
'Day', // 7
|
||||
'Year' // 8
|
||||
];
|
||||
var subjectPlurals = [
|
||||
'Years', // 0
|
||||
'Months', // 1
|
||||
'Days' // 2
|
||||
];
|
||||
var unitsWithin = [
|
||||
12, // months in year
|
||||
31, // days in month (sort of)
|
||||
24, // hours in day
|
||||
60, // minutes in hour
|
||||
60, // seconds in minute
|
||||
1000, // milliseconds in second
|
||||
1 //
|
||||
];
|
||||
var formatStringRE = new RegExp(
|
||||
"(([a-zA-Z])\\2*)|" + // 1, 2
|
||||
"(\\(" + "(('.*?'|\\(.*?\\)|.)*?)" + "\\))|" + // 3, 4, 5 (allows for 1 level of inner quotes or parens)
|
||||
"('(.*?)')" // 6, 7
|
||||
);
|
||||
var UTC = Date.UTC;
|
||||
var toUTCString = Date.prototype.toUTCString;
|
||||
var proto = XDate.prototype;
|
||||
|
||||
|
||||
|
||||
// This makes an XDate look pretty in Firebug and Web Inspector.
|
||||
// It makes an XDate seem array-like, and displays [ <internal-date>.toString() ]
|
||||
proto.length = 1;
|
||||
proto.splice = Array.prototype.splice;
|
||||
|
||||
|
||||
|
||||
|
||||
/* Constructor
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
// TODO: in future, I'd change signature for the constructor regarding the `true` utc-mode param. ~ashaw
|
||||
// I'd move the boolean to be the *first* argument. Still optional. Seems cleaner.
|
||||
// I'd remove it from the `xdate`, `nativeDate`, and `milliseconds` constructors.
|
||||
// (because you can simply call .setUTCMode(true) after)
|
||||
// And I'd only leave it for the y/m/d/h/m/s/m and `dateString` constructors
|
||||
// (because those are the only constructors that need it for DST-gap data-loss reasons)
|
||||
// Should do this for 1.0
|
||||
|
||||
function XDate() {
|
||||
return init(
|
||||
(this instanceof XDate) ? this : new XDate(),
|
||||
arguments
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function init(xdate, args) {
|
||||
var len = args.length;
|
||||
var utcMode;
|
||||
if (isBoolean(args[len-1])) {
|
||||
utcMode = args[--len];
|
||||
args = slice(args, 0, len);
|
||||
}
|
||||
if (!len) {
|
||||
xdate[0] = new Date();
|
||||
}
|
||||
else if (len == 1) {
|
||||
var arg = args[0];
|
||||
if (arg instanceof Date || isNumber(arg)) {
|
||||
xdate[0] = new Date(+arg);
|
||||
}
|
||||
else if (arg instanceof XDate) {
|
||||
xdate[0] = _clone(arg);
|
||||
}
|
||||
else if (isString(arg)) {
|
||||
xdate[0] = new Date(0);
|
||||
xdate = parse(arg, utcMode || false, xdate);
|
||||
}
|
||||
}
|
||||
else {
|
||||
xdate[0] = new Date(UTC.apply(Date, args));
|
||||
if (!utcMode) {
|
||||
xdate[0] = coerceToLocal(xdate[0]);
|
||||
}
|
||||
}
|
||||
if (isBoolean(utcMode)) {
|
||||
setUTCMode(xdate, utcMode);
|
||||
}
|
||||
return xdate;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* UTC Mode Methods
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
proto.getUTCMode = methodize(getUTCMode);
|
||||
function getUTCMode(xdate) {
|
||||
return xdate[0].toString === toUTCString;
|
||||
};
|
||||
|
||||
|
||||
proto.setUTCMode = methodize(setUTCMode);
|
||||
function setUTCMode(xdate, utcMode, doCoercion) {
|
||||
if (utcMode) {
|
||||
if (!getUTCMode(xdate)) {
|
||||
if (doCoercion) {
|
||||
xdate[0] = coerceToUTC(xdate[0]);
|
||||
}
|
||||
xdate[0].toString = toUTCString;
|
||||
}
|
||||
}else{
|
||||
if (getUTCMode(xdate)) {
|
||||
if (doCoercion) {
|
||||
xdate[0] = coerceToLocal(xdate[0]);
|
||||
}else{
|
||||
xdate[0] = new Date(+xdate[0]);
|
||||
}
|
||||
// toString will have been cleared
|
||||
}
|
||||
}
|
||||
return xdate; // for chaining
|
||||
}
|
||||
|
||||
|
||||
proto.getTimezoneOffset = function() {
|
||||
if (getUTCMode(this)) {
|
||||
return 0;
|
||||
}else{
|
||||
return this[0].getTimezoneOffset();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* get / set / add / diff Methods (except for week-related)
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
each(methodSubjects, function(subject, fieldIndex) {
|
||||
|
||||
proto['get' + subject] = function() {
|
||||
return _getField(this[0], getUTCMode(this), fieldIndex);
|
||||
};
|
||||
|
||||
if (fieldIndex != YEAR) { // because there is no getUTCYear
|
||||
|
||||
proto['getUTC' + subject] = function() {
|
||||
return _getField(this[0], true, fieldIndex);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
if (fieldIndex != DAY) { // because there is no setDay or setUTCDay
|
||||
// and the add* and diff* methods use DATE instead
|
||||
|
||||
proto['set' + subject] = function(value) {
|
||||
_set(this, fieldIndex, value, arguments, getUTCMode(this));
|
||||
return this; // for chaining
|
||||
};
|
||||
|
||||
if (fieldIndex != YEAR) { // because there is no setUTCYear
|
||||
// and the add* and diff* methods use FULLYEAR instead
|
||||
|
||||
proto['setUTC' + subject] = function(value) {
|
||||
_set(this, fieldIndex, value, arguments, true);
|
||||
return this; // for chaining
|
||||
};
|
||||
|
||||
proto['add' + (subjectPlurals[fieldIndex] || subject)] = function(delta, preventOverflow) {
|
||||
_add(this, fieldIndex, delta, preventOverflow);
|
||||
return this; // for chaining
|
||||
};
|
||||
|
||||
proto['diff' + (subjectPlurals[fieldIndex] || subject)] = function(otherDate) {
|
||||
return _diff(this, otherDate, fieldIndex);
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
function _set(xdate, fieldIndex, value, args, useUTC) {
|
||||
var getField = curry(_getField, xdate[0], useUTC);
|
||||
var setField = curry(_setField, xdate[0], useUTC);
|
||||
var expectedMonth;
|
||||
var preventOverflow = false;
|
||||
if (args.length == 2 && isBoolean(args[1])) {
|
||||
preventOverflow = args[1];
|
||||
args = [ value ];
|
||||
}
|
||||
if (fieldIndex == MONTH) {
|
||||
expectedMonth = (value % 12 + 12) % 12;
|
||||
}else{
|
||||
expectedMonth = getField(MONTH);
|
||||
}
|
||||
setField(fieldIndex, args);
|
||||
if (preventOverflow && getField(MONTH) != expectedMonth) {
|
||||
setField(MONTH, [ getField(MONTH) - 1 ]);
|
||||
setField(DATE, [ getDaysInMonth(getField(FULLYEAR), getField(MONTH)) ]);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _add(xdate, fieldIndex, delta, preventOverflow) {
|
||||
delta = Number(delta);
|
||||
var intDelta = Math.floor(delta);
|
||||
xdate['set' + methodSubjects[fieldIndex]](
|
||||
xdate['get' + methodSubjects[fieldIndex]]() + intDelta,
|
||||
preventOverflow || false
|
||||
);
|
||||
if (intDelta != delta && fieldIndex < MILLISECONDS) {
|
||||
_add(xdate, fieldIndex+1, (delta-intDelta)*unitsWithin[fieldIndex], preventOverflow);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _diff(xdate1, xdate2, fieldIndex) { // fieldIndex=FULLYEAR is for years, fieldIndex=DATE is for days
|
||||
xdate1 = xdate1.clone().setUTCMode(true, true);
|
||||
xdate2 = XDate(xdate2).setUTCMode(true, true);
|
||||
var v = 0;
|
||||
if (fieldIndex == FULLYEAR || fieldIndex == MONTH) {
|
||||
for (var i=MILLISECONDS, methodName; i>=fieldIndex; i--) {
|
||||
v /= unitsWithin[i];
|
||||
v += _getField(xdate2, false, i) - _getField(xdate1, false, i);
|
||||
}
|
||||
if (fieldIndex == MONTH) {
|
||||
v += (xdate2.getFullYear() - xdate1.getFullYear()) * 12;
|
||||
}
|
||||
}
|
||||
else if (fieldIndex == DATE) {
|
||||
var clear1 = xdate1.toDate().setUTCHours(0, 0, 0, 0); // returns an ms value
|
||||
var clear2 = xdate2.toDate().setUTCHours(0, 0, 0, 0); // returns an ms value
|
||||
v = Math.round((clear2 - clear1) / DAY_MS) + ((xdate2 - clear2) - (xdate1 - clear1)) / DAY_MS;
|
||||
}
|
||||
else {
|
||||
v = (xdate2 - xdate1) / [
|
||||
3600000, // milliseconds in hour
|
||||
60000, // milliseconds in minute
|
||||
1000, // milliseconds in second
|
||||
1 //
|
||||
][fieldIndex - 3];
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Week Methods
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
proto.getWeek = function() {
|
||||
return _getWeek(curry(_getField, this, false));
|
||||
};
|
||||
|
||||
|
||||
proto.getUTCWeek = function() {
|
||||
return _getWeek(curry(_getField, this, true));
|
||||
};
|
||||
|
||||
|
||||
proto.setWeek = function(n, year) {
|
||||
_setWeek(this, n, year, false);
|
||||
return this; // for chaining
|
||||
};
|
||||
|
||||
|
||||
proto.setUTCWeek = function(n, year) {
|
||||
_setWeek(this, n, year, true);
|
||||
return this; // for chaining
|
||||
};
|
||||
|
||||
|
||||
proto.addWeeks = function(delta) {
|
||||
return this.addDays(Number(delta) * 7);
|
||||
};
|
||||
|
||||
|
||||
proto.diffWeeks = function(otherDate) {
|
||||
return _diff(this, otherDate, DATE) / 7;
|
||||
};
|
||||
|
||||
|
||||
function _getWeek(getField) {
|
||||
return getWeek(getField(FULLYEAR), getField(MONTH), getField(DATE));
|
||||
}
|
||||
|
||||
|
||||
function getWeek(year, month, date) {
|
||||
var d = new Date(UTC(year, month, date));
|
||||
var week1 = getWeek1(
|
||||
getWeekYear(year, month, date)
|
||||
);
|
||||
return Math.floor(Math.round((d - week1) / DAY_MS) / 7) + 1;
|
||||
}
|
||||
|
||||
|
||||
function getWeekYear(year, month, date) { // get the year that the date's week # belongs to
|
||||
var d = new Date(UTC(year, month, date));
|
||||
if (d < getWeek1(year)) {
|
||||
return year - 1;
|
||||
}
|
||||
else if (d >= getWeek1(year + 1)) {
|
||||
return year + 1;
|
||||
}
|
||||
return year;
|
||||
}
|
||||
|
||||
|
||||
function getWeek1(year) { // returns Date of first week of year, in UTC
|
||||
var d = new Date(UTC(year, 0, 4));
|
||||
d.setUTCDate(d.getUTCDate() - (d.getUTCDay() + 6) % 7); // make it Monday of the week
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
function _setWeek(xdate, n, year, useUTC) {
|
||||
var getField = curry(_getField, xdate, useUTC);
|
||||
var setField = curry(_setField, xdate, useUTC);
|
||||
|
||||
if (year === undefined) {
|
||||
year = getWeekYear(
|
||||
getField(FULLYEAR),
|
||||
getField(MONTH),
|
||||
getField(DATE)
|
||||
);
|
||||
}
|
||||
|
||||
var week1 = getWeek1(year);
|
||||
if (!useUTC) {
|
||||
week1 = coerceToLocal(week1);
|
||||
}
|
||||
|
||||
xdate.setTime(+week1);
|
||||
setField(DATE, [ getField(DATE) + (n-1) * 7 ]); // would have used xdate.addUTCWeeks :(
|
||||
// n-1 because n is 1-based
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Parsing
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
XDate.parsers = [
|
||||
parseISO
|
||||
];
|
||||
|
||||
|
||||
XDate.parse = function(str) {
|
||||
return +XDate(''+str);
|
||||
};
|
||||
|
||||
|
||||
function parse(str, utcMode, xdate) {
|
||||
var parsers = XDate.parsers;
|
||||
var i = 0;
|
||||
var res;
|
||||
for (; i<parsers.length; i++) {
|
||||
res = parsers[i](str, utcMode, xdate);
|
||||
if (res) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
xdate[0] = new Date(str);
|
||||
return xdate;
|
||||
}
|
||||
|
||||
|
||||
function parseISO(str, utcMode, xdate) {
|
||||
var m = str.match(/^(\d{4})(-(\d{2})(-(\d{2})([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d+))?)?(Z|(([-+])(\d{2})(:?(\d{2}))?))?)?)?)?$/);
|
||||
if (m) {
|
||||
var d = new Date(UTC(
|
||||
m[1],
|
||||
m[3] ? m[3] - 1 : 0,
|
||||
m[5] || 1,
|
||||
m[7] || 0,
|
||||
m[8] || 0,
|
||||
m[10] || 0,
|
||||
m[12] ? Number('0.' + m[12]) * 1000 : 0
|
||||
));
|
||||
if (m[13]) { // has gmt offset or Z
|
||||
if (m[14]) { // has gmt offset
|
||||
d.setUTCMinutes(
|
||||
d.getUTCMinutes() +
|
||||
(m[15] == '-' ? 1 : -1) * (Number(m[16]) * 60 + (m[18] ? Number(m[18]) : 0))
|
||||
);
|
||||
}
|
||||
}else{ // no specified timezone
|
||||
if (!utcMode) {
|
||||
d = coerceToLocal(d);
|
||||
}
|
||||
}
|
||||
return xdate.setTime(+d);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Formatting
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
proto.toString = function(formatString, settings, uniqueness) {
|
||||
if (formatString === undefined || !valid(this)) {
|
||||
return this[0].toString(); // already accounts for utc-mode (might be toUTCString)
|
||||
}else{
|
||||
return format(this, formatString, settings, uniqueness, getUTCMode(this));
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
proto.toUTCString = proto.toGMTString = function(formatString, settings, uniqueness) {
|
||||
if (formatString === undefined || !valid(this)) {
|
||||
return this[0].toUTCString();
|
||||
}else{
|
||||
return format(this, formatString, settings, uniqueness, true);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
proto.toISOString = function() {
|
||||
return this.toUTCString(ISO_FORMAT_STRING_TZ);
|
||||
};
|
||||
|
||||
|
||||
XDate.defaultLocale = '';
|
||||
XDate.locales = {
|
||||
'': {
|
||||
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'],
|
||||
amDesignator: 'AM',
|
||||
pmDesignator: 'PM'
|
||||
}
|
||||
};
|
||||
XDate.formatters = {
|
||||
i: ISO_FORMAT_STRING,
|
||||
u: ISO_FORMAT_STRING_TZ
|
||||
};
|
||||
|
||||
|
||||
function format(xdate, formatString, settings, uniqueness, useUTC) {
|
||||
|
||||
var locales = XDate.locales;
|
||||
var defaultLocaleSettings = locales[XDate.defaultLocale] || {};
|
||||
var getField = curry(_getField, xdate, useUTC);
|
||||
|
||||
settings = (isString(settings) ? locales[settings] : settings) || {};
|
||||
|
||||
function getSetting(name) {
|
||||
return settings[name] || defaultLocaleSettings[name];
|
||||
}
|
||||
|
||||
function getFieldAndTrace(fieldIndex) {
|
||||
if (uniqueness) {
|
||||
var i = (fieldIndex == DAY ? DATE : fieldIndex) - 1;
|
||||
for (; i>=0; i--) {
|
||||
uniqueness.push(getField(i));
|
||||
}
|
||||
}
|
||||
return getField(fieldIndex);
|
||||
}
|
||||
|
||||
return _format(xdate, formatString, getFieldAndTrace, getSetting, useUTC);
|
||||
}
|
||||
|
||||
|
||||
function _format(xdate, formatString, getField, getSetting, useUTC) {
|
||||
var m;
|
||||
var subout;
|
||||
var out = '';
|
||||
while (m = formatString.match(formatStringRE)) {
|
||||
out += formatString.substr(0, m.index);
|
||||
if (m[1]) { // consecutive alphabetic characters
|
||||
out += processTokenString(xdate, m[1], getField, getSetting, useUTC);
|
||||
}
|
||||
else if (m[3]) { // parenthesis
|
||||
subout = _format(xdate, m[4], getField, getSetting, useUTC);
|
||||
if (parseInt(subout.replace(/\D/g, ''), 10)) { // if any of the numbers are non-zero. or no numbers at all
|
||||
out += subout;
|
||||
}
|
||||
}
|
||||
else { // else if (m[6]) { // single quotes
|
||||
out += m[7] || "'"; // if inner is blank, meaning 2 consecutive quotes = literal single quote
|
||||
}
|
||||
formatString = formatString.substr(m.index + m[0].length);
|
||||
}
|
||||
return out + formatString;
|
||||
}
|
||||
|
||||
|
||||
function processTokenString(xdate, tokenString, getField, getSetting, useUTC) {
|
||||
var end = tokenString.length;
|
||||
var replacement;
|
||||
var out = '';
|
||||
while (end > 0) {
|
||||
replacement = getTokenReplacement(xdate, tokenString.substr(0, end), getField, getSetting, useUTC);
|
||||
if (replacement !== undefined) {
|
||||
out += replacement;
|
||||
tokenString = tokenString.substr(end);
|
||||
end = tokenString.length;
|
||||
}else{
|
||||
end--;
|
||||
}
|
||||
}
|
||||
return out + tokenString;
|
||||
}
|
||||
|
||||
|
||||
function getTokenReplacement(xdate, token, getField, getSetting, useUTC) {
|
||||
var formatter = XDate.formatters[token];
|
||||
if (isString(formatter)) {
|
||||
return _format(xdate, formatter, getField, getSetting, useUTC);
|
||||
}
|
||||
else if (isFunction(formatter)) {
|
||||
return formatter(xdate, useUTC || false, getSetting);
|
||||
}
|
||||
switch (token) {
|
||||
case 'fff' : return zeroPad(getField(MILLISECONDS), 3);
|
||||
case 's' : return getField(SECONDS);
|
||||
case 'ss' : return zeroPad(getField(SECONDS));
|
||||
case 'm' : return getField(MINUTES);
|
||||
case 'mm' : return zeroPad(getField(MINUTES));
|
||||
case 'h' : return getField(HOURS) % 12 || 12;
|
||||
case 'hh' : return zeroPad(getField(HOURS) % 12 || 12);
|
||||
case 'H' : return getField(HOURS);
|
||||
case 'HH' : return zeroPad(getField(HOURS));
|
||||
case 'd' : return getField(DATE);
|
||||
case 'dd' : return zeroPad(getField(DATE));
|
||||
case 'ddd' : return getSetting('dayNamesShort')[getField(DAY)] || '';
|
||||
case 'dddd' : return getSetting('dayNames')[getField(DAY)] || '';
|
||||
case 'M' : return getField(MONTH) + 1;
|
||||
case 'MM' : return zeroPad(getField(MONTH) + 1);
|
||||
case 'MMM' : return getSetting('monthNamesShort')[getField(MONTH)] || '';
|
||||
case 'MMMM' : return getSetting('monthNames')[getField(MONTH)] || '';
|
||||
case 'yy' : return (getField(FULLYEAR)+'').substring(2);
|
||||
case 'yyyy' : return getField(FULLYEAR);
|
||||
case 't' : return _getDesignator(getField, getSetting).substr(0, 1).toLowerCase();
|
||||
case 'tt' : return _getDesignator(getField, getSetting).toLowerCase();
|
||||
case 'T' : return _getDesignator(getField, getSetting).substr(0, 1);
|
||||
case 'TT' : return _getDesignator(getField, getSetting);
|
||||
case 'z' :
|
||||
case 'zz' :
|
||||
case 'zzz' : return useUTC ? 'Z' : _getTZString(xdate, token);
|
||||
case 'w' : return _getWeek(getField);
|
||||
case 'ww' : return zeroPad(_getWeek(getField));
|
||||
case 'S' :
|
||||
var d = getField(DATE);
|
||||
if (d > 10 && d < 20) return 'th';
|
||||
return ['st', 'nd', 'rd'][d % 10 - 1] || 'th';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _getTZString(xdate, token) {
|
||||
var tzo = xdate.getTimezoneOffset();
|
||||
var sign = tzo < 0 ? '+' : '-';
|
||||
var hours = Math.floor(Math.abs(tzo) / 60);
|
||||
var minutes = Math.abs(tzo) % 60;
|
||||
var out = hours;
|
||||
if (token == 'zz') {
|
||||
out = zeroPad(hours);
|
||||
}
|
||||
else if (token == 'zzz') {
|
||||
out = zeroPad(hours) + ':' + zeroPad(minutes);
|
||||
}
|
||||
return sign + out;
|
||||
}
|
||||
|
||||
|
||||
function _getDesignator(getField, getSetting) {
|
||||
return getField(HOURS) < 12 ? getSetting('amDesignator') : getSetting('pmDesignator');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Misc Methods
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
each(
|
||||
[ // other getters
|
||||
'getTime',
|
||||
'valueOf',
|
||||
'toDateString',
|
||||
'toTimeString',
|
||||
'toLocaleString',
|
||||
'toLocaleDateString',
|
||||
'toLocaleTimeString',
|
||||
'toJSON'
|
||||
],
|
||||
function(methodName) {
|
||||
proto[methodName] = function() {
|
||||
return this[0][methodName]();
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
proto.setTime = function(t) {
|
||||
this[0].setTime(t);
|
||||
return this; // for chaining
|
||||
};
|
||||
|
||||
|
||||
proto.valid = methodize(valid);
|
||||
function valid(xdate) {
|
||||
return !isNaN(+xdate[0]);
|
||||
}
|
||||
|
||||
|
||||
proto.clone = function() {
|
||||
return new XDate(this);
|
||||
};
|
||||
|
||||
|
||||
proto.clearTime = function() {
|
||||
return this.setHours(0, 0, 0, 0); // will return an XDate for chaining
|
||||
};
|
||||
|
||||
|
||||
proto.toDate = function() {
|
||||
return new Date(+this[0]);
|
||||
};
|
||||
|
||||
|
||||
|
||||
/* Misc Class Methods
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
XDate.now = function() {
|
||||
return +new Date();
|
||||
};
|
||||
|
||||
|
||||
XDate.today = function() {
|
||||
return new XDate().clearTime();
|
||||
};
|
||||
|
||||
|
||||
XDate.UTC = UTC;
|
||||
|
||||
|
||||
XDate.getDaysInMonth = getDaysInMonth;
|
||||
|
||||
|
||||
|
||||
/* Internal Utilities
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function _clone(xdate) { // returns the internal Date object that should be used
|
||||
var d = new Date(+xdate[0]);
|
||||
if (getUTCMode(xdate)) {
|
||||
d.toString = toUTCString;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
function _getField(d, useUTC, fieldIndex) {
|
||||
return d['get' + (useUTC ? 'UTC' : '') + methodSubjects[fieldIndex]]();
|
||||
}
|
||||
|
||||
|
||||
function _setField(d, useUTC, fieldIndex, args) {
|
||||
d['set' + (useUTC ? 'UTC' : '') + methodSubjects[fieldIndex]].apply(d, args);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* Date Math Utilities
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function coerceToUTC(date) {
|
||||
return new Date(UTC(
|
||||
date.getFullYear(),
|
||||
date.getMonth(),
|
||||
date.getDate(),
|
||||
date.getHours(),
|
||||
date.getMinutes(),
|
||||
date.getSeconds(),
|
||||
date.getMilliseconds()
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
function coerceToLocal(date) {
|
||||
return new Date(
|
||||
date.getUTCFullYear(),
|
||||
date.getUTCMonth(),
|
||||
date.getUTCDate(),
|
||||
date.getUTCHours(),
|
||||
date.getUTCMinutes(),
|
||||
date.getUTCSeconds(),
|
||||
date.getUTCMilliseconds()
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function getDaysInMonth(year, month) {
|
||||
return 32 - new Date(UTC(year, month, 32)).getUTCDate();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* General Utilities
|
||||
---------------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
function methodize(f) {
|
||||
return function() {
|
||||
return f.apply(undefined, [this].concat(slice(arguments)));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function curry(f) {
|
||||
var firstArgs = slice(arguments, 1);
|
||||
return function() {
|
||||
return f.apply(undefined, firstArgs.concat(slice(arguments)));
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function slice(a, start, end) {
|
||||
return Array.prototype.slice.call(
|
||||
a,
|
||||
start || 0, // start and end cannot be undefined for IE
|
||||
end===undefined ? a.length : end
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
function each(a, f) {
|
||||
for (var i=0; i<a.length; i++) {
|
||||
f(a[i], i);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function isString(arg) {
|
||||
return typeof arg == 'string';
|
||||
}
|
||||
|
||||
|
||||
function isNumber(arg) {
|
||||
return typeof arg == 'number';
|
||||
}
|
||||
|
||||
|
||||
function isBoolean(arg) {
|
||||
return typeof arg == 'boolean';
|
||||
}
|
||||
|
||||
|
||||
function isFunction(arg) {
|
||||
return typeof arg == 'function';
|
||||
}
|
||||
|
||||
|
||||
function zeroPad(n, len) {
|
||||
len = len || 2;
|
||||
n += '';
|
||||
while (n.length < len) {
|
||||
n = '0' + n;
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Export for Node.js
|
||||
if (typeof module !== 'undefined' && module.exports) {
|
||||
module.exports = XDate;
|
||||
}
|
||||
|
||||
// AMD
|
||||
if (typeof define === 'function' && define.amd) {
|
||||
define([], function() {
|
||||
return XDate;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
return XDate;
|
||||
|
||||
})(Date, Math, Array);
|
||||
Reference in New Issue
Block a user