Files
Chamilo/main/inc/lib/javascript/epiclock/javascript/jquery.dateformat.js
2025-08-14 22:37:50 +02:00

706 lines
19 KiB
JavaScript

/*!
* Date formatting plugin
*
* Copyright (c) Eric Garside
* Dual licensed under:
* MIT: http://www.opensource.org/licenses/mit-license.php
* GPLv3: http://www.opensource.org/licenses/gpl-3.0.html
*/
"use strict";
/*global jQuery */
/*jslint white: true, browser: true, onevar: true, undef: true, eqeqeq: true, bitwise: true, regexp: true, strict: true, newcap: true, immed: true, maxerr: 50, indent: 4 */
(function ($) {
//------------------------------
//
// Property Declaration
//
//------------------------------
/**
* String formatting for each month, with January at index "0" and December at "11".
*/
var months = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
/**
* String formatting for each day, with Sunday at index "0" and Saturday at index "6"
*/
days = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
/**
* The number of days in each month.
*/
counts = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31],
/**
* English ordinal suffix for corresponding days of the week.
*/
suffix = [null, 'st', 'nd', 'rd'],
/**
* Define the object which will hold reference to the actual formatting functions. By not directly prototyping these
* into the date function, we vastly reduce the amount of bloat adding these options causes.
*/
_;
//------------------------------
//
// Internal Methods
//
//------------------------------
/**
* Left-pad the string with the provided string up to the provided length.
*
* @param format The string to pad.
*
* @param string The string to pad with.
*
* @param length The length to make the string (default is "0" if undefined).
*
* @return The padded string.
*/
function pad(format, string, length)
{
format = format + '';
length = length || 2;
return format.length < length ? new Array(1 + length - format.length).join(string) + format : format;
}
/**
* Right-pad the string with the provided string up to the provided length.
*
* @param format The string to pad.
*
* @param string The string to pad with.
*
* @param length The length to make the string (default is "0" if undefined).
*
* @return The padded string.
*/
function rpad(format, string, length)
{
format = format + '';
length = length || 2;
return format.length < length ? format + new Array(1 + length - format.length).join(string) : format;
}
/**
* Perform a modulus calculation on a date object to extract the desired value.
*
* @param date The date object to perform the calculation on.
*
* @param mod1 The value to divide the date value seconds by.
*
* @param mod2 The modulus value.
*
* @return The computed value.
*/
function modCalc(date, mod1, mod2)
{
return (Math.floor(Math.floor(date.valueOf() / 1e3) / mod1) % mod2);
}
/**
* Given a string, return a properly formatted date string.
*
* @param date The date object being formatted.
*
* @param format The formatting string.
*
* @return The formatted date string
*/
function formatDate(date, format)
{
format = format.split('');
var output = '',
/**
* The characters '{' and '}' are the start and end characters of an escape. Anything between these
* characters will not be treated as a formatting commands, and will merely be appended to the output
* string. When the buffering property here is true, we are in the midst of appending escaped characters
* to the output, and the formatting check should therefore be skipped.
*/
buffering = false,
char = '',
index = 0;
for (; index < format.length; index++)
{
char = format[index] + '';
switch (char)
{
case ' ':
output += char;
break;
case '{':
case '}':
buffering = char === '{';
break;
default:
if (!buffering && _[char])
{
output += _[char].apply(date);
}
else
{
output += char;
}
break;
}
}
return output;
}
//------------------------------
//
// Class Definition
//
//------------------------------
/**
* The formatting object holds all the actual formatting commands which should be accessible
* for date formatting.
*
* Each method should reference the date function via its "this" context, which will be set
* by the formatter.
*
* This function makes heavy use of the exponent notation for large numbers, to save space. In
* javascript, any number with a set of trailing zeros can be expressed in exponent notation.
*
* Ex. 15,000,000,000 === 15e9, where the number after "e" represents the number of zeros.
*/
_ =
{
//------------------------------
// Timer Formatting
//------------------------------
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of days since the epoch.
*/
V: function ()
{
return modCalc(this, 864e2, 1e5);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of days since the epoch, padded to 2 digits.
*/
v: function ()
{
return pad(_.V.apply(this), 0);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of days since the epoch, offset for years.
*/
K: function ()
{
return _.V.apply(this) % 365;
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of days since the epoch, offset for years, padded to 2 digits.
*/
k: function ()
{
return pad(_.K.apply(this), 0);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of hours since the epoch.
*/
X: function ()
{
return modCalc(this, 36e2, 24);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of hours since the epoch, padded to two digits.
*/
x: function ()
{
return pad(_.X.apply(this), 0);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of minutes since the epoch.
*/
p: function ()
{
return modCalc(this, 60, 60);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of minutes since the epoch, padded to two digits.
*/
C: function ()
{
return pad(_.p.apply(this), 0);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of minutes since the epoch, uncapped. (1min 30seconds would be 90s)
*/
E: function ()
{
return (_.X.apply(this) * 60) + _.p.apply(this);
},
/**
* This is intended to be used for delta computation when subtracting one date object from another.
*
* @return The number of minutes since the epoch, uncapped and padded to two digits. (1min 30seconds would be 90s)
*/
e: function ()
{
return pad(_.e.apply(this), 0);
},
//------------------------------
// Day Formatting
//------------------------------
/**
* @return The day of the month, padded to two digits.
*/
d: function ()
{
return pad(this.getDate(), 0);
},
/**
* @return A textual representation of the day, three letters.
*/
D: function ()
{
return days[this.getDay()].substring(0, 3);
},
/**
* @return Day of the month without leading zeros.
*/
j: function ()
{
return this.getDate();
},
/**
* @return A full textual representation of the day of the week.
*/
l: function ()
{
return days[this.getDay()];
},
/**
* @return ISO-8601 numeric representation of the day of the week.
*/
N: function ()
{
return this.getDay() + 1;
},
/**
* @return English ordinal suffix for the day of the month, two characters.
*/
S: function ()
{
return suffix[this.getDate()] || 'th';
},
/**
* @return Numeric representation of the day of the week.
*/
w: function ()
{
return this.getDay();
},
/**
* @return The day of the year (starting from 0).
*/
z: function ()
{
return Math.round((this - _.f.apply(this)) / 864e5);
},
//------------------------------
// Week
//------------------------------
/**
* @return ISO-8601 week number of year, weeks starting on Monday
*/
W: function ()
{
return Math.ceil(((((this - _.f.apply(this)) / 864e5) + _.w.apply(_.f.apply(this))) / 7));
},
//------------------------------
// Month
//------------------------------
/**
* @return A full textual representation of a month, such as January.
*/
F: function ()
{
return months[this.getMonth()];
},
/**
* @return Numeric representation of a month, padded to two digits.
*/
m: function ()
{
return pad((this.getMonth() + 1), 0);
},
/**
* @return A short textual representation of a month, three letters.
*/
M: function ()
{
return months[this.getMonth()].substring(0, 3);
},
/**
* @return Numeric representation of a month, without leading zeros.
*/
n: function ()
{
return this.getMonth() + 1;
},
/**
* @return Number of days in the given month.
*/
t: function ()
{
// For February on leap years, we must return 29.
if (this.getMonth() === 1 && _.L.apply(this) === 1)
{
return 29;
}
return counts[this.getMonth()];
},
//------------------------------
// Year
//------------------------------
/**
* @return Whether it's a leap year. 1 if it is a leap year, 0 otherwise.
*/
L: function ()
{
var Y = _.Y.apply(this);
return Y % 4 ? 0 : Y % 100 ? 1 : Y % 400 ? 0 : 1;
},
/**
* @return A Date object representing the first day of the current year.
*/
f: function ()
{
return new Date(this.getFullYear(), 0, 1);
},
/**
* @return A full numeric representation of the year, 4 digits.
*/
Y: function ()
{
return this.getFullYear();
},
/**
* @return A two digit representation of the year.
*/
y: function ()
{
return ('' + this.getFullYear()).substr(2);
},
//------------------------------
// Time
//------------------------------
/**
* @return Lowercase Ante/Post Meridiem values.
*/
a: function ()
{
return this.getHours() < 12 ? 'am' : 'pm';
},
/**
* @return Uppercase Ante/Post Meridiem values.
*/
A: function ()
{
return _.a.apply(this).toUpperCase();
},
/**
* If you ever use this for anything, email <eric@knewton.com>, cause he'd like to know how you found this nonsense useful.
*
* @return Swatch internet time.
*/
B: function ()
{
return pad(Math.floor((((this.getHours()) * 36e5) + (this.getMinutes() * 6e4) + (this.getSeconds() * 1e3)) / 864e2), 0, 3);
},
/**
* @return 12-hour format of an hour.
*/
g: function ()
{
return this.getHours() % 12 || 12;
},
/**
* @return 24-hour format of an hour.
*/
G: function ()
{
return this.getHours();
},
/**
* @return 12-hour format of an hour, padded to two digits.
*/
h: function ()
{
return pad(_.g.apply(this), 0);
},
/**
* @return 24-hour format of an hour, padded to two digits.
*/
H: function ()
{
return pad(this.getHours(), 0);
},
/**
* @return Minutes, padded to two digits.
*/
i: function ()
{
return pad(this.getMinutes(), 0);
},
/**
* @return Seconds, padded to two digits.
*/
s: function ()
{
return pad(this.getSeconds(), 0);
},
/**
* @return Microseconds
*/
u: function ()
{
return this.getTime() % 1e3;
},
//------------------------------
// Timezone
//------------------------------
/**
* @return Difference to GMT in hours.
*/
O: function ()
{
var t = this.getTimezoneOffset() / 60;
return rpad(pad((t >= 0 ? '+' : '-') + Math.abs(t), 0), 0, 4);
},
/**
* @return Difference to GMT in hours, with colon between hours and minutes
*/
P: function ()
{
var t = _.O.apply(this);
return t.subst(0, 3) + ':' + t.substr(3);
},
/**
* @return Timezone offset in seconds.
*/
Z: function ()
{
return this.getTimezoneOffset() * 60;
},
//------------------------------
// Full Date/Time
//------------------------------
/**
* @return ISO 8601 date
*/
c: function ()
{
return _.Y.apply(this) + '-' + _.m.apply(this) + '-' + _.d.apply(this) + 'T' + _.H.apply(this) + ':' + _.i.apply(this) + ':' + _.s.apply(this) + _.P.apply(this);
},
/**
* @return RFC 2822 formatted date
*/
r: function ()
{
return this.toString();
},
/**
* @return The number of seconds since the epoch.
*/
U: function ()
{
return this.getTime() / 1e3;
}
};
//------------------------------
//
// Native Prototype
//
//------------------------------
$.extend(Date.prototype, {
/**
* Given a string of formatting commands, return the date object as a formatted string.
*
* @param format The formatting string.
*
* @return The formatted date string
*/
format: function (format)
{
return formatDate(this, format);
}
});
//------------------------------
//
// Expose to jQuery
//
//------------------------------
$.dateformat =
{
/**
* Get a reference to the formatting rules, or set custom rules.
*
* @param custom The custom rules to set for formatting.
*
* @return The formatting rules.
*/
rules: function (custom)
{
if (custom !== undefined)
{
_ = $.extend(_, custom);
}
return _;
},
/**
* Determine if the dateformat plugin has the requested formatting rule.
*
* @param rule The formatting rule to check.
*
* @return True if the rule exists, false otherwise.
*/
hasRule: function (rule)
{
return _[rule] !== undefined;
},
/**
* Get a formatting value for a given date.
*
* @param type The formatting character type to get the value of.
*
* @param date The date to extract the value from. Defaults to current.
*/
get: function (type, date)
{
return _[type].apply(date || new Date());
},
/**
* Given a string of formatting commands, return the date object as a formatted string.
*
* @param format The formatting string.
*
* @param date The date to extract the value from. Defaults to current.
*
* @return The formatted date string
*/
format: function (format, date)
{
return formatDate(date || new Date(), format);
},
/**
* @inheritDoc
*/
pad: pad,
/**
* @inheritDoc
*/
rpad: rpad
};
}(jQuery));