706 lines
19 KiB
JavaScript
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));
|