aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
// format tokens
- formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?)/g,
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|.)/g,
localFormattingTokens = /(LT|LL?L?L?)/g,
- formattingRemoveEscapes = /(^\[)|(\\)|\]$/g,
// parsing tokens
parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
// format function strings
formatFunctions = {},
+ // tokens to ordinalize and pad
+ ordinalizeTokens = 'DDD w M D d'.split(' '),
+ paddedTokens = 'M D H h m s w'.split(' '),
+
/*
* moment.fn.format uses new Function() to create an inlined formatting function.
* Results are a 3x speed boost
*
* These strings are appended into a function using replaceFormatTokens and makeFormatFunction
*/
- formatFunctionStrings = {
+ formatTokenFunctions = {
// a = placeholder
// b = placeholder
// t = the current moment being formatted
// o = language.ordinal function
// p = leftZeroFill function
// m = language.meridiem value or function
- M : '(a=t.month()+1)',
- MMM : 'v("monthsShort",t.month())',
- MMMM : 'v("months",t.month())',
- D : '(a=t.date())',
- DDD : '(a=new Date(t.year(),t.month(),t.date()),b=new Date(t.year(),0,1),a=~~(((a-b)/864e5)+1.5))',
- d : '(a=t.day())',
- dd : 'v("weekdaysMin",t.day())',
- ddd : 'v("weekdaysShort",t.day())',
- dddd : 'v("weekdays",t.day())',
- w : '(a=new Date(t.year(),t.month(),t.date()-t.day()+5),b=new Date(a.getFullYear(),0,4),a=~~((a-b)/864e5/7+1.5))',
- YY : 'p(t.year()%100,2)',
- YYYY : 'p(t.year(),4)',
- a : 'm(t.hours(),t.minutes(),!0)',
- A : 'm(t.hours(),t.minutes(),!1)',
- H : 't.hours()',
- h : 't.hours()%12||12',
- m : 't.minutes()',
- s : 't.seconds()',
- S : '~~(t.milliseconds()/100)',
- SS : 'p(~~(t.milliseconds()/10),2)',
- SSS : 'p(t.milliseconds(),3)',
- Z : '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(a/60),2)+":"+p(~~a%60,2)',
- ZZ : '((a=-t.zone())<0?((a=-a),"-"):"+")+p(~~(10*a/6),4)'
- },
+ M : function () {
+ return this.month() + 1;
+ },
+ MMM : function (format) {
+ return getValueFromArray("monthsShort", this.month(), this, format);
+ },
+ MMMM : function (format) {
+ return getValueFromArray("months", this.month(), this, format);
+ },
+ D : function () {
+ return this.date();
+ },
+ DDD : function () {
+ var a = new Date(this.year(), this.month(), this.date()),
+ b = new Date(this.year(), 0, 1);
+ return ~~(((a - b) / 864e5) + 1.5);
+ },
+ d : function () {
+ return this.day();
+ },
+ dd : function (format) {
+ return getValueFromArray("weekdaysMin", this.day(), this, format);
+ },
+ ddd : function (format) {
+ return getValueFromArray("weekdaysShort", this.day(), this, format);
+ },
+ dddd : function (format) {
+ return getValueFromArray("weekdays", this.day(), this, format);
+ },
+ w : function () {
+ var a = new Date(this.year(), this.month(), this.date() - this.day() + 5),
+ b = new Date(a.getFullYear(), 0, 4);
+ return ~~((a - b) / 864e5 / 7 + 1.5);
+ },
+ YY : function () {
+ return leftZeroFill(this.year() % 100, 2);
+ },
+ YYYY : function () {
+ return leftZeroFill(this.year(), 4);
+ },
+ a : function () {
+ return this.lang().meridiem(this.hours(), this.minutes(), true);
+ },
+ A : function () {
+ return this.lang().meridiem(this.hours(), this.minutes(), false);
+ },
+ H : function () {
+ return this.hours();
+ },
+ h : function () {
+ return this.hours() % 12 || 12;
+ },
+ m : function () {
+ return this.minutes();
+ },
+ s : function () {
+ return this.seconds();
+ },
+ S : function () {
+ return ~~(this.milliseconds() / 100);
+ },
+ SS : function () {
+ return leftZeroFill(~~(this.milliseconds() / 10), 2);
+ },
+ SSS : function () {
+ return leftZeroFill(this.milliseconds(), 3);
+ },
+ Z : function () {
+ var a = -this.zone(),
+ b = "+";
+ if (a < 0) {
+ a = -a;
+ b = "-";
+ }
+ return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2);
+ },
+ ZZ : function () {
+ var a = -this.zone(),
+ b = "+";
+ if (a < 0) {
+ a = -a;
+ b = "-";
+ }
+ return b + leftZeroFill(~~(10 * a / 6), 4);
+ }
+ };
- ordinalizeTokens = 'DDD w M D d'.split(' '),
- paddedTokens = 'M D H h m s w'.split(' ');
+ function getValueFromArray(key, index, m, format) {
+ var lang = m.lang();
+ return lang[key].call ? lang[key](m, format) : lang[key][index];
+ }
+
+ function padToken(func, count) {
+ return function (a) {
+ return leftZeroFill(func.call(this, a), count);
+ };
+ }
+ function ordinalizeToken(func) {
+ return function (a) {
+ var b = func.call(this, a);
+ return b + this.lang().ordinal(b);
+ };
+ }
while (ordinalizeTokens.length) {
i = ordinalizeTokens.pop();
- formatFunctionStrings[i + 'o'] = formatFunctionStrings[i] + '+o(a)';
+ formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
}
while (paddedTokens.length) {
i = paddedTokens.pop();
- formatFunctionStrings[i + i] = 'p(' + formatFunctionStrings[i] + ',2)';
+ formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
}
- formatFunctionStrings.DDDD = 'p(' + formatFunctionStrings.DDD + ',3)';
+ formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
/************************************
************************************/
- // helper for building inline formatting functions
- function replaceFormatTokens(token) {
- return formatFunctionStrings[token] ?
- ("'+(" + formatFunctionStrings[token] + ")+'") :
- token.replace(formattingRemoveEscapes, "").replace(/\\?'/g, "\\'");
- }
-
// helper for recursing long date formatting tokens
function replaceLongDateFormatTokens(input) {
return getLangDefinition().longDateFormat[input] || input;
}
- function makeFormatFunction(format) {
- var output = "var a,b;return '" +
- format.replace(formattingTokens, replaceFormatTokens) + "';",
- Fn = Function; // get around jshint
- // t = the current moment being formatted
- // v = getValueAtKey function
- // o = language.ordinal function
- // p = leftZeroFill function
- // m = language.meridiem value or function
- return new Fn('t', 'v', 'o', 'p', 'm', output);
+ function removeFormattingTokens(input) {
+ if (input.match(/\[.*\]/)) {
+ return input.replace(/^\[|\]$/g, "");
+ }
+ return input.replace(/\\/g, "");
}
- function makeOrGetFormatFunction(format) {
- if (!formatFunctions[format]) {
- formatFunctions[format] = makeFormatFunction(format);
+ function makeFormatFunction(format) {
+ var array = format.match(formattingTokens), i, length;
+
+ for (i = 0, length = array.length; i < length; i++) {
+ if (formatTokenFunctions[array[i]]) {
+ array[i] = formatTokenFunctions[array[i]];
+ } else {
+ array[i] = removeFormattingTokens(array[i]);
+ }
}
- return formatFunctions[format];
+
+ return function (mom) {
+ var output = "";
+ for (i = 0; i < length; i++) {
+ output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i];
+ }
+ return output;
+ };
}
// format date using native date object
function formatMoment(m, format) {
- var lang = getLangDefinition(m);
-
- function getValueFromArray(key, index) {
- return lang[key].call ? lang[key](m, format) : lang[key][index];
- }
-
while (localFormattingTokens.test(format)) {
format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
}
formatFunctions[format] = makeFormatFunction(format);
}
- return formatFunctions[format](m, getValueFromArray, lang.ordinal, leftZeroFill, lang.meridiem);
+ return formatFunctions[format](m);
}