diff --git a/_includes/recline-deps.html b/_includes/recline-deps.html
index ab67cf19..f4969418 100644
--- a/_includes/recline-deps.html
+++ b/_includes/recline-deps.html
@@ -34,7 +34,7 @@
-
+
-
+
{% endhighlight %}
diff --git a/test/index.html b/test/index.html
index e15ce778..5d4f44ea 100644
--- a/test/index.html
+++ b/test/index.html
@@ -11,7 +11,7 @@
-
+
diff --git a/vendor/moment/1.6.2/moment.js b/vendor/moment/1.6.2/moment.js
deleted file mode 100644
index c7901d27..00000000
--- a/vendor/moment/1.6.2/moment.js
+++ /dev/null
@@ -1,918 +0,0 @@
-// moment.js
-// version : 1.6.2
-// author : Tim Wood
-// license : MIT
-// momentjs.com
-
-(function (Date, undefined) {
-
- var moment,
- VERSION = "1.6.2",
- round = Math.round, i,
- // internal storage for language config files
- languages = {},
- currentLanguage = 'en',
-
- // check for nodeJS
- hasModule = (typeof module !== 'undefined'),
-
- // parameters to check for on the lang config
- langConfigProperties = 'months|monthsShort|monthsParse|weekdays|weekdaysShort|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
-
- // ASP.NET json date format regex
- aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
-
- // format tokens
- formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|dddd?|do?|w[o|w]?|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|zz?|ZZ?|LT|LL?L?L?)/g,
-
- // parsing tokens
- parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
-
- // parsing token regexes
- parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
- parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
- parseTokenThreeDigits = /\d{3}/, // 000 - 999
- parseTokenFourDigits = /\d{4}/, // 0000 - 9999
- parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, // any word characters or numbers
- parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
- parseTokenT = /T/i, // T (ISO seperator)
-
- // preliminary iso regex
- // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
- isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
- isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
-
- // iso time formats and regexes
- isoTimes = [
- ['HH:mm:ss.S', /T\d\d:\d\d:\d\d\.\d{1,3}/],
- ['HH:mm:ss', /T\d\d:\d\d:\d\d/],
- ['HH:mm', /T\d\d:\d\d/],
- ['HH', /T\d\d/]
- ],
-
- // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
- parseTimezoneChunker = /([\+\-]|\d\d)/gi,
-
- // getter and setter names
- proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
- unitMillisecondFactors = {
- 'Milliseconds' : 1,
- 'Seconds' : 1e3,
- 'Minutes' : 6e4,
- 'Hours' : 36e5,
- 'Days' : 864e5,
- 'Months' : 2592e6,
- 'Years' : 31536e6
- };
-
- // Moment prototype object
- function Moment(date, isUTC) {
- this._d = date;
- this._isUTC = !!isUTC;
- }
-
- function absRound(number) {
- if (number < 0) {
- return Math.ceil(number);
- } else {
- return Math.floor(number);
- }
- }
-
- // Duration Constructor
- function Duration(duration) {
- var data = this._data = {},
- years = duration.years || duration.y || 0,
- months = duration.months || duration.M || 0,
- weeks = duration.weeks || duration.w || 0,
- days = duration.days || duration.d || 0,
- hours = duration.hours || duration.h || 0,
- minutes = duration.minutes || duration.m || 0,
- seconds = duration.seconds || duration.s || 0,
- milliseconds = duration.milliseconds || duration.ms || 0;
-
- // representation for dateAddRemove
- this._milliseconds = milliseconds +
- seconds * 1e3 + // 1000
- minutes * 6e4 + // 1000 * 60
- hours * 36e5; // 1000 * 60 * 60
- // Because of dateAddRemove treats 24 hours as different from a
- // day when working around DST, we need to store them separately
- this._days = days +
- weeks * 7;
- // It is impossible translate months into days without knowing
- // which months you are are talking about, so we have to store
- // it separately.
- this._months = months +
- years * 12;
-
- // The following code bubbles up values, see the tests for
- // examples of what that means.
- data.milliseconds = milliseconds % 1000;
- seconds += absRound(milliseconds / 1000);
-
- data.seconds = seconds % 60;
- minutes += absRound(seconds / 60);
-
- data.minutes = minutes % 60;
- hours += absRound(minutes / 60);
-
- data.hours = hours % 24;
- days += absRound(hours / 24);
-
- days += weeks * 7;
- data.days = days % 30;
-
- months += absRound(days / 30);
-
- data.months = months % 12;
- years += absRound(months / 12);
-
- data.years = years;
- }
-
- // left zero fill a number
- // see http://jsperf.com/left-zero-filling for performance comparison
- function leftZeroFill(number, targetLength) {
- var output = number + '';
- while (output.length < targetLength) {
- output = '0' + output;
- }
- return output;
- }
-
- // helper function for _.addTime and _.subtractTime
- function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
- var ms = duration._milliseconds,
- d = duration._days,
- M = duration._months,
- currentDate;
-
- if (ms) {
- mom._d.setTime(+mom + ms * isAdding);
- }
- if (d) {
- mom.date(mom.date() + d * isAdding);
- }
- if (M) {
- currentDate = mom.date();
- mom.date(1)
- .month(mom.month() + M * isAdding)
- .date(Math.min(currentDate, mom.daysInMonth()));
- }
- }
-
- // check if is an array
- function isArray(input) {
- return Object.prototype.toString.call(input) === '[object Array]';
- }
-
- // convert an array to a date.
- // the array should mirror the parameters below
- // note: all values past the year are optional and will default to the lowest possible value.
- // [year, month, day , hour, minute, second, millisecond]
- function dateFromArray(input) {
- return new Date(input[0], input[1] || 0, input[2] || 1, input[3] || 0, input[4] || 0, input[5] || 0, input[6] || 0);
- }
-
- // format date using native date object
- function formatMoment(m, inputString) {
- var currentMonth = m.month(),
- currentDate = m.date(),
- currentYear = m.year(),
- currentDay = m.day(),
- currentHours = m.hours(),
- currentMinutes = m.minutes(),
- currentSeconds = m.seconds(),
- currentMilliseconds = m.milliseconds(),
- currentZone = -m.zone(),
- ordinal = moment.ordinal,
- meridiem = moment.meridiem;
- // check if the character is a format
- // return formatted string or non string.
- //
- // uses switch/case instead of an object of named functions (like http://phpjs.org/functions/date:380)
- // for minification and performance
- // see http://jsperf.com/object-of-functions-vs-switch for performance comparison
- function replaceFunction(input) {
- // create a couple variables to be used later inside one of the cases.
- var a, b;
- switch (input) {
- // MONTH
- case 'M' :
- return currentMonth + 1;
- case 'Mo' :
- return (currentMonth + 1) + ordinal(currentMonth + 1);
- case 'MM' :
- return leftZeroFill(currentMonth + 1, 2);
- case 'MMM' :
- return moment.monthsShort[currentMonth];
- case 'MMMM' :
- return moment.months[currentMonth];
- // DAY OF MONTH
- case 'D' :
- return currentDate;
- case 'Do' :
- return currentDate + ordinal(currentDate);
- case 'DD' :
- return leftZeroFill(currentDate, 2);
- // DAY OF YEAR
- case 'DDD' :
- a = new Date(currentYear, currentMonth, currentDate);
- b = new Date(currentYear, 0, 1);
- return ~~ (((a - b) / 864e5) + 1.5);
- case 'DDDo' :
- a = replaceFunction('DDD');
- return a + ordinal(a);
- case 'DDDD' :
- return leftZeroFill(replaceFunction('DDD'), 3);
- // WEEKDAY
- case 'd' :
- return currentDay;
- case 'do' :
- return currentDay + ordinal(currentDay);
- case 'ddd' :
- return moment.weekdaysShort[currentDay];
- case 'dddd' :
- return moment.weekdays[currentDay];
- // WEEK OF YEAR
- case 'w' :
- a = new Date(currentYear, currentMonth, currentDate - currentDay + 5);
- b = new Date(a.getFullYear(), 0, 4);
- return ~~ ((a - b) / 864e5 / 7 + 1.5);
- case 'wo' :
- a = replaceFunction('w');
- return a + ordinal(a);
- case 'ww' :
- return leftZeroFill(replaceFunction('w'), 2);
- // YEAR
- case 'YY' :
- return leftZeroFill(currentYear % 100, 2);
- case 'YYYY' :
- return currentYear;
- // AM / PM
- case 'a' :
- return meridiem ? meridiem(currentHours, currentMinutes, false) : (currentHours > 11 ? 'pm' : 'am');
- case 'A' :
- return meridiem ? meridiem(currentHours, currentMinutes, true) : (currentHours > 11 ? 'PM' : 'AM');
- // 24 HOUR
- case 'H' :
- return currentHours;
- case 'HH' :
- return leftZeroFill(currentHours, 2);
- // 12 HOUR
- case 'h' :
- return currentHours % 12 || 12;
- case 'hh' :
- return leftZeroFill(currentHours % 12 || 12, 2);
- // MINUTE
- case 'm' :
- return currentMinutes;
- case 'mm' :
- return leftZeroFill(currentMinutes, 2);
- // SECOND
- case 's' :
- return currentSeconds;
- case 'ss' :
- return leftZeroFill(currentSeconds, 2);
- // MILLISECONDS
- case 'S' :
- return ~~ (currentMilliseconds / 100);
- case 'SS' :
- return leftZeroFill(~~(currentMilliseconds / 10), 2);
- case 'SSS' :
- return leftZeroFill(currentMilliseconds, 3);
- // TIMEZONE
- case 'Z' :
- return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(Math.abs(currentZone) / 60), 2) + ':' + leftZeroFill(~~(Math.abs(currentZone) % 60), 2);
- case 'ZZ' :
- return (currentZone < 0 ? '-' : '+') + leftZeroFill(~~(10 * Math.abs(currentZone) / 6), 4);
- // LONG DATES
- case 'L' :
- case 'LL' :
- case 'LLL' :
- case 'LLLL' :
- case 'LT' :
- return formatMoment(m, moment.longDateFormat[input]);
- // DEFAULT
- default :
- return input.replace(/(^\[)|(\\)|\]$/g, "");
- }
- }
- return inputString.replace(formattingTokens, replaceFunction);
- }
-
- // get the regex to find the next token
- function getParseRegexForToken(token) {
- switch (token) {
- case 'DDDD':
- return parseTokenThreeDigits;
- case 'YYYY':
- return parseTokenFourDigits;
- case 'S':
- case 'SS':
- case 'SSS':
- case 'DDD':
- return parseTokenOneToThreeDigits;
- case 'MMM':
- case 'MMMM':
- case 'ddd':
- case 'dddd':
- case 'a':
- case 'A':
- return parseTokenWord;
- case 'Z':
- case 'ZZ':
- return parseTokenTimezone;
- case 'T':
- return parseTokenT;
- case 'MM':
- case 'DD':
- case 'dd':
- case 'YY':
- case 'HH':
- case 'hh':
- case 'mm':
- case 'ss':
- case 'M':
- case 'D':
- case 'd':
- case 'H':
- case 'h':
- case 'm':
- case 's':
- return parseTokenOneOrTwoDigits;
- default :
- return new RegExp(token.replace('\\', ''));
- }
- }
-
- // function to convert string input to date
- function addTimeToArrayFromToken(token, input, datePartArray, config) {
- var a;
- //console.log('addTime', format, input);
- switch (token) {
- // MONTH
- case 'M' : // fall through to MM
- case 'MM' :
- datePartArray[1] = (input == null) ? 0 : ~~input - 1;
- break;
- case 'MMM' : // fall through to MMMM
- case 'MMMM' :
- for (a = 0; a < 12; a++) {
- if (moment.monthsParse[a].test(input)) {
- datePartArray[1] = a;
- break;
- }
- }
- break;
- // DAY OF MONTH
- case 'D' : // fall through to DDDD
- case 'DD' : // fall through to DDDD
- case 'DDD' : // fall through to DDDD
- case 'DDDD' :
- datePartArray[2] = ~~input;
- break;
- // YEAR
- case 'YY' :
- input = ~~input;
- datePartArray[0] = input + (input > 70 ? 1900 : 2000);
- break;
- case 'YYYY' :
- datePartArray[0] = ~~Math.abs(input);
- break;
- // AM / PM
- case 'a' : // fall through to A
- case 'A' :
- config.isPm = ((input + '').toLowerCase() === 'pm');
- break;
- // 24 HOUR
- case 'H' : // fall through to hh
- case 'HH' : // fall through to hh
- case 'h' : // fall through to hh
- case 'hh' :
- datePartArray[3] = ~~input;
- break;
- // MINUTE
- case 'm' : // fall through to mm
- case 'mm' :
- datePartArray[4] = ~~input;
- break;
- // SECOND
- case 's' : // fall through to ss
- case 'ss' :
- datePartArray[5] = ~~input;
- break;
- // MILLISECOND
- case 'S' :
- case 'SS' :
- case 'SSS' :
- datePartArray[6] = ~~ (('0.' + input) * 1000);
- break;
- // TIMEZONE
- case 'Z' : // fall through to ZZ
- case 'ZZ' :
- config.isUTC = true;
- a = (input + '').match(parseTimezoneChunker);
- if (a && a[1]) {
- config.tzh = ~~a[1];
- }
- if (a && a[2]) {
- config.tzm = ~~a[2];
- }
- // reverse offsets
- if (a && a[0] === '+') {
- config.tzh = -config.tzh;
- config.tzm = -config.tzm;
- }
- break;
- }
- }
-
- // date from string and format string
- function makeDateFromStringAndFormat(string, format) {
- var datePartArray = [0, 0, 1, 0, 0, 0, 0],
- config = {
- tzh : 0, // timezone hour offset
- tzm : 0 // timezone minute offset
- },
- tokens = format.match(formattingTokens),
- i, parsedInput;
-
- for (i = 0; i < tokens.length; i++) {
- parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
- string = string.replace(getParseRegexForToken(tokens[i]), '');
- addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config);
- }
- // handle am pm
- if (config.isPm && datePartArray[3] < 12) {
- datePartArray[3] += 12;
- }
- // if is 12 am, change hours to 0
- if (config.isPm === false && datePartArray[3] === 12) {
- datePartArray[3] = 0;
- }
- // handle timezone
- datePartArray[3] += config.tzh;
- datePartArray[4] += config.tzm;
- // return
- return config.isUTC ? new Date(Date.UTC.apply({}, datePartArray)) : dateFromArray(datePartArray);
- }
-
- // compare two arrays, return the number of differences
- function compareArrays(array1, array2) {
- var len = Math.min(array1.length, array2.length),
- lengthDiff = Math.abs(array1.length - array2.length),
- diffs = 0,
- i;
- for (i = 0; i < len; i++) {
- if (~~array1[i] !== ~~array2[i]) {
- diffs++;
- }
- }
- return diffs + lengthDiff;
- }
-
- // date from string and array of format strings
- function makeDateFromStringAndArray(string, formats) {
- var output,
- inputParts = string.match(parseMultipleFormatChunker) || [],
- formattedInputParts,
- scoreToBeat = 99,
- i,
- currentDate,
- currentScore;
- for (i = 0; i < formats.length; i++) {
- currentDate = makeDateFromStringAndFormat(string, formats[i]);
- formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
- currentScore = compareArrays(inputParts, formattedInputParts);
- if (currentScore < scoreToBeat) {
- scoreToBeat = currentScore;
- output = currentDate;
- }
- }
- return output;
- }
-
- // date from iso format
- function makeDateFromString(string) {
- var format = 'YYYY-MM-DDT',
- i;
- if (isoRegex.exec(string)) {
- for (i = 0; i < 4; i++) {
- if (isoTimes[i][1].exec(string)) {
- format += isoTimes[i][0];
- break;
- }
- }
- return parseTokenTimezone.exec(string) ?
- makeDateFromStringAndFormat(string, format + ' Z') :
- makeDateFromStringAndFormat(string, format);
- }
- return new Date(string);
- }
-
- // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
- function substituteTimeAgo(string, number, withoutSuffix, isFuture) {
- var rt = moment.relativeTime[string];
- return (typeof rt === 'function') ?
- rt(number || 1, !!withoutSuffix, string, isFuture) :
- rt.replace(/%d/i, number || 1);
- }
-
- function relativeTime(milliseconds, withoutSuffix) {
- var seconds = round(Math.abs(milliseconds) / 1000),
- minutes = round(seconds / 60),
- hours = round(minutes / 60),
- days = round(hours / 24),
- years = round(days / 365),
- args = seconds < 45 && ['s', seconds] ||
- minutes === 1 && ['m'] ||
- minutes < 45 && ['mm', minutes] ||
- hours === 1 && ['h'] ||
- hours < 22 && ['hh', hours] ||
- days === 1 && ['d'] ||
- days <= 25 && ['dd', days] ||
- days <= 45 && ['M'] ||
- days < 345 && ['MM', round(days / 30)] ||
- years === 1 && ['y'] || ['yy', years];
- args[2] = withoutSuffix;
- args[3] = milliseconds > 0;
- return substituteTimeAgo.apply({}, args);
- }
-
- moment = function (input, format) {
- if (input === null || input === '') {
- return null;
- }
- var date,
- matched,
- isUTC;
- // parse Moment object
- if (moment.isMoment(input)) {
- date = new Date(+input._d);
- isUTC = input._isUTC;
- // parse string and format
- } else if (format) {
- if (isArray(format)) {
- date = makeDateFromStringAndArray(input, format);
- } else {
- date = makeDateFromStringAndFormat(input, format);
- }
- // evaluate it as a JSON-encoded date
- } else {
- matched = aspNetJsonRegex.exec(input);
- date = input === undefined ? new Date() :
- matched ? new Date(+matched[1]) :
- input instanceof Date ? input :
- isArray(input) ? dateFromArray(input) :
- typeof input === 'string' ? makeDateFromString(input) :
- new Date(input);
- }
- return new Moment(date, isUTC);
- };
-
- // creating with utc
- moment.utc = function (input, format) {
- if (isArray(input)) {
- return new Moment(new Date(Date.UTC.apply({}, input)), true);
- }
- return (format && input) ?
- moment(input + ' +0000', format + ' Z').utc() :
- moment(input && !parseTokenTimezone.exec(input) ? input + '+0000' : input).utc();
- };
-
- // creating with unix timestamp (in seconds)
- moment.unix = function (input) {
- return moment(input * 1000);
- };
-
- // duration
- moment.duration = function (input, key) {
- var isDuration = moment.isDuration(input),
- isNumber = (typeof input === 'number'),
- duration = (isDuration ? input._data : (isNumber ? {} : input));
-
- if (isNumber) {
- if (key) {
- duration[key] = input;
- } else {
- duration.milliseconds = input;
- }
- }
-
- return new Duration(duration);
- };
-
- // humanizeDuration
- // This method is deprecated in favor of the new Duration object. Please
- // see the moment.duration method.
- moment.humanizeDuration = function (num, type, withSuffix) {
- return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix);
- };
-
- // version number
- moment.version = VERSION;
-
- // default format
- moment.defaultFormat = isoFormat;
-
- // language switching and caching
- moment.lang = function (key, values) {
- var i, req,
- parse = [];
- if (!key) {
- return currentLanguage;
- }
- if (values) {
- for (i = 0; i < 12; i++) {
- parse[i] = new RegExp('^' + values.months[i] + '|^' + values.monthsShort[i].replace('.', ''), 'i');
- }
- values.monthsParse = values.monthsParse || parse;
- languages[key] = values;
- }
- if (languages[key]) {
- for (i = 0; i < langConfigProperties.length; i++) {
- moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]] ||
- languages.en[langConfigProperties[i]];
- }
- currentLanguage = key;
- } else {
- if (hasModule) {
- req = require('./lang/' + key);
- moment.lang(key, req);
- }
- }
- };
-
- // set default language
- moment.lang('en', {
- months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
- monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
- weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
- weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
- longDateFormat : {
- LT : "h:mm A",
- L : "MM/DD/YYYY",
- LL : "MMMM D YYYY",
- LLL : "MMMM D YYYY LT",
- LLLL : "dddd, MMMM D YYYY LT"
- },
- meridiem : false,
- calendar : {
- sameDay : '[Today at] LT',
- nextDay : '[Tomorrow at] LT',
- nextWeek : 'dddd [at] LT',
- lastDay : '[Yesterday at] LT',
- lastWeek : '[last] dddd [at] LT',
- sameElse : 'L'
- },
- relativeTime : {
- future : "in %s",
- past : "%s ago",
- s : "a few seconds",
- m : "a minute",
- mm : "%d minutes",
- h : "an hour",
- hh : "%d hours",
- d : "a day",
- dd : "%d days",
- M : "a month",
- MM : "%d months",
- y : "a year",
- yy : "%d years"
- },
- ordinal : function (number) {
- var b = number % 10;
- return (~~ (number % 100 / 10) === 1) ? 'th' :
- (b === 1) ? 'st' :
- (b === 2) ? 'nd' :
- (b === 3) ? 'rd' : 'th';
- }
- });
-
- // compare moment object
- moment.isMoment = function (obj) {
- return obj instanceof Moment;
- };
-
- // for typechecking Duration objects
- moment.isDuration = function (obj) {
- return obj instanceof Duration;
- };
-
- // shortcut for prototype
- moment.fn = Moment.prototype = {
-
- clone : function () {
- return moment(this);
- },
-
- valueOf : function () {
- return +this._d;
- },
-
- unix : function () {
- return Math.floor(+this._d / 1000);
- },
-
- toString : function () {
- return this._d.toString();
- },
-
- toDate : function () {
- return this._d;
- },
-
- utc : function () {
- this._isUTC = true;
- return this;
- },
-
- local : function () {
- this._isUTC = false;
- return this;
- },
-
- format : function (inputString) {
- return formatMoment(this, inputString ? inputString : moment.defaultFormat);
- },
-
- add : function (input, val) {
- var dur = val ? moment.duration(+val, input) : moment.duration(input);
- addOrSubtractDurationFromMoment(this, dur, 1);
- return this;
- },
-
- subtract : function (input, val) {
- var dur = val ? moment.duration(+val, input) : moment.duration(input);
- addOrSubtractDurationFromMoment(this, dur, -1);
- return this;
- },
-
- diff : function (input, val, asFloat) {
- var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
- zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
- diff = this._d - inputMoment._d - zoneDiff,
- year = this.year() - inputMoment.year(),
- month = this.month() - inputMoment.month(),
- date = this.date() - inputMoment.date(),
- output;
- if (val === 'months') {
- output = year * 12 + month + date / 30;
- } else if (val === 'years') {
- output = year + (month + date / 30) / 12;
- } else {
- output = val === 'seconds' ? diff / 1e3 : // 1000
- val === 'minutes' ? diff / 6e4 : // 1000 * 60
- val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
- val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
- val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
- diff;
- }
- return asFloat ? output : round(output);
- },
-
- from : function (time, withoutSuffix) {
- return moment.duration(this.diff(time)).humanize(!withoutSuffix);
- },
-
- fromNow : function (withoutSuffix) {
- return this.from(moment(), withoutSuffix);
- },
-
- calendar : function () {
- var diff = this.diff(moment().sod(), 'days', true),
- calendar = moment.calendar,
- allElse = calendar.sameElse,
- format = diff < -6 ? allElse :
- diff < -1 ? calendar.lastWeek :
- diff < 0 ? calendar.lastDay :
- diff < 1 ? calendar.sameDay :
- diff < 2 ? calendar.nextDay :
- diff < 7 ? calendar.nextWeek : allElse;
- return this.format(typeof format === 'function' ? format.apply(this) : format);
- },
-
- isLeapYear : function () {
- var year = this.year();
- return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
- },
-
- isDST : function () {
- return (this.zone() < moment([this.year()]).zone() ||
- this.zone() < moment([this.year(), 5]).zone());
- },
-
- day : function (input) {
- var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
- return input == null ? day :
- this.add({ d : input - day });
- },
-
- sod: function () {
- return moment(this)
- .hours(0)
- .minutes(0)
- .seconds(0)
- .milliseconds(0);
- },
-
- eod: function () {
- // end of day = start of day plus 1 day, minus 1 millisecond
- return this.sod().add({
- d : 1,
- ms : -1
- });
- },
-
- zone : function () {
- return this._isUTC ? 0 : this._d.getTimezoneOffset();
- },
-
- daysInMonth : function () {
- return moment(this).month(this.month() + 1).date(0).date();
- }
- };
-
- // helper for adding shortcuts
- function makeGetterAndSetter(name, key) {
- moment.fn[name] = function (input) {
- var utc = this._isUTC ? 'UTC' : '';
- if (input != null) {
- this._d['set' + utc + key](input);
- return this;
- } else {
- return this._d['get' + utc + key]();
- }
- };
- }
-
- // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
- for (i = 0; i < proxyGettersAndSetters.length; i ++) {
- makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i]);
- }
-
- // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
- makeGetterAndSetter('year', 'FullYear');
-
- moment.duration.fn = Duration.prototype = {
- weeks : function () {
- return absRound(this.days() / 7);
- },
-
- valueOf : function () {
- return this._milliseconds +
- this._days * 864e5 +
- this._months * 2592e6;
- },
-
- humanize : function (withSuffix) {
- var difference = +this,
- rel = moment.relativeTime,
- output = relativeTime(difference, !withSuffix);
-
- if (withSuffix) {
- output = (difference <= 0 ? rel.past : rel.future).replace(/%s/i, output);
- }
-
- return output;
- }
- };
-
- function makeDurationGetter(name) {
- moment.duration.fn[name] = function () {
- return this._data[name];
- };
- }
-
- function makeDurationAsGetter(name, factor) {
- moment.duration.fn['as' + name] = function () {
- return +this / factor;
- };
- }
-
- for (i in unitMillisecondFactors) {
- if (unitMillisecondFactors.hasOwnProperty(i)) {
- makeDurationAsGetter(i, unitMillisecondFactors[i]);
- makeDurationGetter(i.toLowerCase());
- }
- }
-
- makeDurationAsGetter('Weeks', 6048e5);
-
- // CommonJS module is defined
- if (hasModule) {
- module.exports = moment;
- }
- /*global ender:false */
- if (typeof window !== 'undefined' && typeof ender === 'undefined') {
- window.moment = moment;
- }
- /*global define:false */
- if (typeof define === "function" && define.amd) {
- define("moment", [], function () {
- return moment;
- });
- }
-})(Date);
diff --git a/vendor/moment/2.0.0/moment.js b/vendor/moment/2.0.0/moment.js
new file mode 100644
index 00000000..9ff57aac
--- /dev/null
+++ b/vendor/moment/2.0.0/moment.js
@@ -0,0 +1,1400 @@
+// moment.js
+// version : 2.0.0
+// author : Tim Wood
+// license : MIT
+// momentjs.com
+
+(function (undefined) {
+
+ /************************************
+ Constants
+ ************************************/
+
+ var moment,
+ VERSION = "2.0.0",
+ round = Math.round, i,
+ // internal storage for language config files
+ languages = {},
+
+ // check for nodeJS
+ hasModule = (typeof module !== 'undefined' && module.exports),
+
+ // ASP.NET json date format regex
+ aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
+
+ // format tokens
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,
+ localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
+
+ // parsing tokens
+ parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
+
+ // parsing token regexes
+ parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
+ parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
+ parseTokenThreeDigits = /\d{3}/, // 000 - 999
+ parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
+ parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
+ parseTokenWord = /[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i, // any word (or two) characters or numbers including two word month in arabic.
+ parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
+ parseTokenT = /T/i, // T (ISO seperator)
+ parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
+
+ // preliminary iso regex
+ // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
+ isoRegex = /^\s*\d{4}-\d\d-\d\d((T| )(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
+ isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
+
+ // iso time formats and regexes
+ isoTimes = [
+ ['HH:mm:ss.S', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
+ ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
+ ['HH:mm', /(T| )\d\d:\d\d/],
+ ['HH', /(T| )\d\d/]
+ ],
+
+ // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
+ parseTimezoneChunker = /([\+\-]|\d\d)/gi,
+
+ // getter and setter names
+ proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
+ unitMillisecondFactors = {
+ 'Milliseconds' : 1,
+ 'Seconds' : 1e3,
+ 'Minutes' : 6e4,
+ 'Hours' : 36e5,
+ 'Days' : 864e5,
+ 'Months' : 2592e6,
+ 'Years' : 31536e6
+ },
+
+ // format function strings
+ formatFunctions = {},
+
+ // tokens to ordinalize and pad
+ ordinalizeTokens = 'DDD w W M D d'.split(' '),
+ paddedTokens = 'M D H h m s w W'.split(' '),
+
+ formatTokenFunctions = {
+ M : function () {
+ return this.month() + 1;
+ },
+ MMM : function (format) {
+ return this.lang().monthsShort(this, format);
+ },
+ MMMM : function (format) {
+ return this.lang().months(this, format);
+ },
+ D : function () {
+ return this.date();
+ },
+ DDD : function () {
+ return this.dayOfYear();
+ },
+ d : function () {
+ return this.day();
+ },
+ dd : function (format) {
+ return this.lang().weekdaysMin(this, format);
+ },
+ ddd : function (format) {
+ return this.lang().weekdaysShort(this, format);
+ },
+ dddd : function (format) {
+ return this.lang().weekdays(this, format);
+ },
+ w : function () {
+ return this.week();
+ },
+ W : function () {
+ return this.isoWeek();
+ },
+ YY : function () {
+ return leftZeroFill(this.year() % 100, 2);
+ },
+ YYYY : function () {
+ return leftZeroFill(this.year(), 4);
+ },
+ YYYYY : function () {
+ return leftZeroFill(this.year(), 5);
+ },
+ 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);
+ },
+ X : function () {
+ return this.unix();
+ }
+ };
+
+ function padToken(func, count) {
+ return function (a) {
+ return leftZeroFill(func.call(this, a), count);
+ };
+ }
+ function ordinalizeToken(func) {
+ return function (a) {
+ return this.lang().ordinal(func.call(this, a));
+ };
+ }
+
+ while (ordinalizeTokens.length) {
+ i = ordinalizeTokens.pop();
+ formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
+ }
+ while (paddedTokens.length) {
+ i = paddedTokens.pop();
+ formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
+ }
+ formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
+
+
+ /************************************
+ Constructors
+ ************************************/
+
+ function Language() {
+
+ }
+
+ // Moment prototype object
+ function Moment(config) {
+ extend(this, config);
+ }
+
+ // Duration Constructor
+ function Duration(duration) {
+ var data = this._data = {},
+ years = duration.years || duration.year || duration.y || 0,
+ months = duration.months || duration.month || duration.M || 0,
+ weeks = duration.weeks || duration.week || duration.w || 0,
+ days = duration.days || duration.day || duration.d || 0,
+ hours = duration.hours || duration.hour || duration.h || 0,
+ minutes = duration.minutes || duration.minute || duration.m || 0,
+ seconds = duration.seconds || duration.second || duration.s || 0,
+ milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0;
+
+ // representation for dateAddRemove
+ this._milliseconds = milliseconds +
+ seconds * 1e3 + // 1000
+ minutes * 6e4 + // 1000 * 60
+ hours * 36e5; // 1000 * 60 * 60
+ // Because of dateAddRemove treats 24 hours as different from a
+ // day when working around DST, we need to store them separately
+ this._days = days +
+ weeks * 7;
+ // It is impossible translate months into days without knowing
+ // which months you are are talking about, so we have to store
+ // it separately.
+ this._months = months +
+ years * 12;
+
+ // The following code bubbles up values, see the tests for
+ // examples of what that means.
+ data.milliseconds = milliseconds % 1000;
+ seconds += absRound(milliseconds / 1000);
+
+ data.seconds = seconds % 60;
+ minutes += absRound(seconds / 60);
+
+ data.minutes = minutes % 60;
+ hours += absRound(minutes / 60);
+
+ data.hours = hours % 24;
+ days += absRound(hours / 24);
+
+ days += weeks * 7;
+ data.days = days % 30;
+
+ months += absRound(days / 30);
+
+ data.months = months % 12;
+ years += absRound(months / 12);
+
+ data.years = years;
+ }
+
+
+ /************************************
+ Helpers
+ ************************************/
+
+
+ function extend(a, b) {
+ for (var i in b) {
+ if (b.hasOwnProperty(i)) {
+ a[i] = b[i];
+ }
+ }
+ return a;
+ }
+
+ function absRound(number) {
+ if (number < 0) {
+ return Math.ceil(number);
+ } else {
+ return Math.floor(number);
+ }
+ }
+
+ // left zero fill a number
+ // see http://jsperf.com/left-zero-filling for performance comparison
+ function leftZeroFill(number, targetLength) {
+ var output = number + '';
+ while (output.length < targetLength) {
+ output = '0' + output;
+ }
+ return output;
+ }
+
+ // helper function for _.addTime and _.subtractTime
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
+ var ms = duration._milliseconds,
+ d = duration._days,
+ M = duration._months,
+ currentDate;
+
+ if (ms) {
+ mom._d.setTime(+mom + ms * isAdding);
+ }
+ if (d) {
+ mom.date(mom.date() + d * isAdding);
+ }
+ if (M) {
+ currentDate = mom.date();
+ mom.date(1)
+ .month(mom.month() + M * isAdding)
+ .date(Math.min(currentDate, mom.daysInMonth()));
+ }
+ }
+
+ // check if is an array
+ function isArray(input) {
+ return Object.prototype.toString.call(input) === '[object Array]';
+ }
+
+ // compare two arrays, return the number of differences
+ function compareArrays(array1, array2) {
+ var len = Math.min(array1.length, array2.length),
+ lengthDiff = Math.abs(array1.length - array2.length),
+ diffs = 0,
+ i;
+ for (i = 0; i < len; i++) {
+ if (~~array1[i] !== ~~array2[i]) {
+ diffs++;
+ }
+ }
+ return diffs + lengthDiff;
+ }
+
+
+ /************************************
+ Languages
+ ************************************/
+
+
+ Language.prototype = {
+ set : function (config) {
+ var prop, i;
+ for (i in config) {
+ prop = config[i];
+ if (typeof prop === 'function') {
+ this[i] = prop;
+ } else {
+ this['_' + i] = prop;
+ }
+ }
+ },
+
+ _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
+ months : function (m) {
+ return this._months[m.month()];
+ },
+
+ _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
+ monthsShort : function (m) {
+ return this._monthsShort[m.month()];
+ },
+
+ monthsParse : function (monthName) {
+ var i, mom, regex, output;
+
+ if (!this._monthsParse) {
+ this._monthsParse = [];
+ }
+
+ for (i = 0; i < 12; i++) {
+ // make the regex if we don't have it already
+ if (!this._monthsParse[i]) {
+ mom = moment([2000, i]);
+ regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
+ this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
+ }
+ // test the regex
+ if (this._monthsParse[i].test(monthName)) {
+ return i;
+ }
+ }
+ },
+
+ _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
+ weekdays : function (m) {
+ return this._weekdays[m.day()];
+ },
+
+ _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
+ weekdaysShort : function (m) {
+ return this._weekdaysShort[m.day()];
+ },
+
+ _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
+ weekdaysMin : function (m) {
+ return this._weekdaysMin[m.day()];
+ },
+
+ _longDateFormat : {
+ LT : "h:mm A",
+ L : "MM/DD/YYYY",
+ LL : "MMMM D YYYY",
+ LLL : "MMMM D YYYY LT",
+ LLLL : "dddd, MMMM D YYYY LT"
+ },
+ longDateFormat : function (key) {
+ var output = this._longDateFormat[key];
+ if (!output && this._longDateFormat[key.toUpperCase()]) {
+ output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) {
+ return val.slice(1);
+ });
+ this._longDateFormat[key] = output;
+ }
+ return output;
+ },
+
+ meridiem : function (hours, minutes, isLower) {
+ if (hours > 11) {
+ return isLower ? 'pm' : 'PM';
+ } else {
+ return isLower ? 'am' : 'AM';
+ }
+ },
+
+ _calendar : {
+ sameDay : '[Today at] LT',
+ nextDay : '[Tomorrow at] LT',
+ nextWeek : 'dddd [at] LT',
+ lastDay : '[Yesterday at] LT',
+ lastWeek : '[last] dddd [at] LT',
+ sameElse : 'L'
+ },
+ calendar : function (key, mom) {
+ var output = this._calendar[key];
+ return typeof output === 'function' ? output.apply(mom) : output;
+ },
+
+ _relativeTime : {
+ future : "in %s",
+ past : "%s ago",
+ s : "a few seconds",
+ m : "a minute",
+ mm : "%d minutes",
+ h : "an hour",
+ hh : "%d hours",
+ d : "a day",
+ dd : "%d days",
+ M : "a month",
+ MM : "%d months",
+ y : "a year",
+ yy : "%d years"
+ },
+ relativeTime : function (number, withoutSuffix, string, isFuture) {
+ var output = this._relativeTime[string];
+ return (typeof output === 'function') ?
+ output(number, withoutSuffix, string, isFuture) :
+ output.replace(/%d/i, number);
+ },
+ pastFuture : function (diff, output) {
+ var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
+ return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
+ },
+
+ ordinal : function (number) {
+ return this._ordinal.replace("%d", number);
+ },
+ _ordinal : "%d",
+
+ preparse : function (string) {
+ return string;
+ },
+
+ postformat : function (string) {
+ return string;
+ },
+
+ week : function (mom) {
+ return weekOfYear(mom, this._week.dow, this._week.doy);
+ },
+ _week : {
+ dow : 0, // Sunday is the first day of the week.
+ doy : 6 // The week that contains Jan 1st is the first week of the year.
+ }
+ };
+
+ // Loads a language definition into the `languages` cache. The function
+ // takes a key and optionally values. If not in the browser and no values
+ // are provided, it will load the language file module. As a convenience,
+ // this function also returns the language values.
+ function loadLang(key, values) {
+ values.abbr = key;
+ if (!languages[key]) {
+ languages[key] = new Language();
+ }
+ languages[key].set(values);
+ return languages[key];
+ }
+
+ // Determines which language definition to use and returns it.
+ //
+ // With no parameters, it will return the global language. If you
+ // pass in a language key, such as 'en', it will return the
+ // definition for 'en', so long as 'en' has already been loaded using
+ // moment.lang.
+ function getLangDefinition(key) {
+ if (!key) {
+ return moment.fn._lang;
+ }
+ if (!languages[key] && hasModule) {
+ require('./lang/' + key);
+ }
+ return languages[key];
+ }
+
+
+ /************************************
+ Formatting
+ ************************************/
+
+
+ function removeFormattingTokens(input) {
+ if (input.match(/\[.*\]/)) {
+ return input.replace(/^\[|\]$/g, "");
+ }
+ return input.replace(/\\/g, "");
+ }
+
+ 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 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 i = 5;
+
+ function replaceLongDateFormatTokens(input) {
+ return m.lang().longDateFormat(input) || input;
+ }
+
+ while (i-- && localFormattingTokens.test(format)) {
+ format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
+ }
+
+ if (!formatFunctions[format]) {
+ formatFunctions[format] = makeFormatFunction(format);
+ }
+
+ return formatFunctions[format](m);
+ }
+
+
+ /************************************
+ Parsing
+ ************************************/
+
+
+ // get the regex to find the next token
+ function getParseRegexForToken(token) {
+ switch (token) {
+ case 'DDDD':
+ return parseTokenThreeDigits;
+ case 'YYYY':
+ return parseTokenFourDigits;
+ case 'YYYYY':
+ return parseTokenSixDigits;
+ case 'S':
+ case 'SS':
+ case 'SSS':
+ case 'DDD':
+ return parseTokenOneToThreeDigits;
+ case 'MMM':
+ case 'MMMM':
+ case 'dd':
+ case 'ddd':
+ case 'dddd':
+ case 'a':
+ case 'A':
+ return parseTokenWord;
+ case 'X':
+ return parseTokenTimestampMs;
+ case 'Z':
+ case 'ZZ':
+ return parseTokenTimezone;
+ case 'T':
+ return parseTokenT;
+ case 'MM':
+ case 'DD':
+ case 'YY':
+ case 'HH':
+ case 'hh':
+ case 'mm':
+ case 'ss':
+ case 'M':
+ case 'D':
+ case 'd':
+ case 'H':
+ case 'h':
+ case 'm':
+ case 's':
+ return parseTokenOneOrTwoDigits;
+ default :
+ return new RegExp(token.replace('\\', ''));
+ }
+ }
+
+ // function to convert string input to date
+ function addTimeToArrayFromToken(token, input, config) {
+ var a, b,
+ datePartArray = config._a;
+
+ switch (token) {
+ // MONTH
+ case 'M' : // fall through to MM
+ case 'MM' :
+ datePartArray[1] = (input == null) ? 0 : ~~input - 1;
+ break;
+ case 'MMM' : // fall through to MMMM
+ case 'MMMM' :
+ a = getLangDefinition(config._l).monthsParse(input);
+ // if we didn't find a month name, mark the date as invalid.
+ if (a != null) {
+ datePartArray[1] = a;
+ } else {
+ config._isValid = false;
+ }
+ break;
+ // DAY OF MONTH
+ case 'D' : // fall through to DDDD
+ case 'DD' : // fall through to DDDD
+ case 'DDD' : // fall through to DDDD
+ case 'DDDD' :
+ if (input != null) {
+ datePartArray[2] = ~~input;
+ }
+ break;
+ // YEAR
+ case 'YY' :
+ datePartArray[0] = ~~input + (~~input > 68 ? 1900 : 2000);
+ break;
+ case 'YYYY' :
+ case 'YYYYY' :
+ datePartArray[0] = ~~input;
+ break;
+ // AM / PM
+ case 'a' : // fall through to A
+ case 'A' :
+ config._isPm = ((input + '').toLowerCase() === 'pm');
+ break;
+ // 24 HOUR
+ case 'H' : // fall through to hh
+ case 'HH' : // fall through to hh
+ case 'h' : // fall through to hh
+ case 'hh' :
+ datePartArray[3] = ~~input;
+ break;
+ // MINUTE
+ case 'm' : // fall through to mm
+ case 'mm' :
+ datePartArray[4] = ~~input;
+ break;
+ // SECOND
+ case 's' : // fall through to ss
+ case 'ss' :
+ datePartArray[5] = ~~input;
+ break;
+ // MILLISECOND
+ case 'S' :
+ case 'SS' :
+ case 'SSS' :
+ datePartArray[6] = ~~ (('0.' + input) * 1000);
+ break;
+ // UNIX TIMESTAMP WITH MS
+ case 'X':
+ config._d = new Date(parseFloat(input) * 1000);
+ break;
+ // TIMEZONE
+ case 'Z' : // fall through to ZZ
+ case 'ZZ' :
+ config._useUTC = true;
+ a = (input + '').match(parseTimezoneChunker);
+ if (a && a[1]) {
+ config._tzh = ~~a[1];
+ }
+ if (a && a[2]) {
+ config._tzm = ~~a[2];
+ }
+ // reverse offsets
+ if (a && a[0] === '+') {
+ config._tzh = -config._tzh;
+ config._tzm = -config._tzm;
+ }
+ break;
+ }
+
+ // if the input is null, the date is not valid
+ if (input == null) {
+ config._isValid = false;
+ }
+ }
+
+ // convert an array to a date.
+ // the array should mirror the parameters below
+ // note: all values past the year are optional and will default to the lowest possible value.
+ // [year, month, day , hour, minute, second, millisecond]
+ function dateFromArray(config) {
+ var i, date, input = [];
+
+ if (config._d) {
+ return;
+ }
+
+ for (i = 0; i < 7; i++) {
+ config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
+ }
+
+ // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
+ input[3] += config._tzh || 0;
+ input[4] += config._tzm || 0;
+
+ date = new Date(0);
+
+ if (config._useUTC) {
+ date.setUTCFullYear(input[0], input[1], input[2]);
+ date.setUTCHours(input[3], input[4], input[5], input[6]);
+ } else {
+ date.setFullYear(input[0], input[1], input[2]);
+ date.setHours(input[3], input[4], input[5], input[6]);
+ }
+
+ config._d = date;
+ }
+
+ // date from string and format string
+ function makeDateFromStringAndFormat(config) {
+ // This array is used to make a Date, either with `new Date` or `Date.UTC`
+ var tokens = config._f.match(formattingTokens),
+ string = config._i,
+ i, parsedInput;
+
+ config._a = [];
+
+ for (i = 0; i < tokens.length; i++) {
+ parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
+ if (parsedInput) {
+ string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
+ }
+ // don't parse if its not a known token
+ if (formatTokenFunctions[tokens[i]]) {
+ addTimeToArrayFromToken(tokens[i], parsedInput, config);
+ }
+ }
+ // handle am pm
+ if (config._isPm && config._a[3] < 12) {
+ config._a[3] += 12;
+ }
+ // if is 12 am, change hours to 0
+ if (config._isPm === false && config._a[3] === 12) {
+ config._a[3] = 0;
+ }
+ // return
+ dateFromArray(config);
+ }
+
+ // date from string and array of format strings
+ function makeDateFromStringAndArray(config) {
+ var tempConfig,
+ tempMoment,
+ bestMoment,
+
+ scoreToBeat = 99,
+ i,
+ currentDate,
+ currentScore;
+
+ while (config._f.length) {
+ tempConfig = extend({}, config);
+ tempConfig._f = config._f.pop();
+ makeDateFromStringAndFormat(tempConfig);
+ tempMoment = new Moment(tempConfig);
+
+ if (tempMoment.isValid()) {
+ bestMoment = tempMoment;
+ break;
+ }
+
+ currentScore = compareArrays(tempConfig._a, tempMoment.toArray());
+
+ if (currentScore < scoreToBeat) {
+ scoreToBeat = currentScore;
+ bestMoment = tempMoment;
+ }
+ }
+
+ extend(config, bestMoment);
+ }
+
+ // date from iso format
+ function makeDateFromString(config) {
+ var i,
+ string = config._i;
+ if (isoRegex.exec(string)) {
+ config._f = 'YYYY-MM-DDT';
+ for (i = 0; i < 4; i++) {
+ if (isoTimes[i][1].exec(string)) {
+ config._f += isoTimes[i][0];
+ break;
+ }
+ }
+ if (parseTokenTimezone.exec(string)) {
+ config._f += " Z";
+ }
+ makeDateFromStringAndFormat(config);
+ } else {
+ config._d = new Date(string);
+ }
+ }
+
+ function makeDateFromInput(config) {
+ var input = config._i,
+ matched = aspNetJsonRegex.exec(input);
+
+ if (input === undefined) {
+ config._d = new Date();
+ } else if (matched) {
+ config._d = new Date(+matched[1]);
+ } else if (typeof input === 'string') {
+ makeDateFromString(config);
+ } else if (isArray(input)) {
+ config._a = input.slice(0);
+ dateFromArray(config);
+ } else {
+ config._d = input instanceof Date ? new Date(+input) : new Date(input);
+ }
+ }
+
+
+ /************************************
+ Relative Time
+ ************************************/
+
+
+ // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
+ return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
+ }
+
+ function relativeTime(milliseconds, withoutSuffix, lang) {
+ var seconds = round(Math.abs(milliseconds) / 1000),
+ minutes = round(seconds / 60),
+ hours = round(minutes / 60),
+ days = round(hours / 24),
+ years = round(days / 365),
+ args = seconds < 45 && ['s', seconds] ||
+ minutes === 1 && ['m'] ||
+ minutes < 45 && ['mm', minutes] ||
+ hours === 1 && ['h'] ||
+ hours < 22 && ['hh', hours] ||
+ days === 1 && ['d'] ||
+ days <= 25 && ['dd', days] ||
+ days <= 45 && ['M'] ||
+ days < 345 && ['MM', round(days / 30)] ||
+ years === 1 && ['y'] || ['yy', years];
+ args[2] = withoutSuffix;
+ args[3] = milliseconds > 0;
+ args[4] = lang;
+ return substituteTimeAgo.apply({}, args);
+ }
+
+
+ /************************************
+ Week of Year
+ ************************************/
+
+
+ // firstDayOfWeek 0 = sun, 6 = sat
+ // the day of the week that starts the week
+ // (usually sunday or monday)
+ // firstDayOfWeekOfYear 0 = sun, 6 = sat
+ // the first week is the week that contains the first
+ // of this day of the week
+ // (eg. ISO weeks use thursday (4))
+ function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
+ var end = firstDayOfWeekOfYear - firstDayOfWeek,
+ daysToDayOfWeek = firstDayOfWeekOfYear - mom.day();
+
+
+ if (daysToDayOfWeek > end) {
+ daysToDayOfWeek -= 7;
+ }
+
+ if (daysToDayOfWeek < end - 7) {
+ daysToDayOfWeek += 7;
+ }
+
+ return Math.ceil(moment(mom).add('d', daysToDayOfWeek).dayOfYear() / 7);
+ }
+
+
+ /************************************
+ Top Level Functions
+ ************************************/
+
+ function makeMoment(config) {
+ var input = config._i,
+ format = config._f;
+
+ if (input === null || input === '') {
+ return null;
+ }
+
+ if (typeof input === 'string') {
+ config._i = input = getLangDefinition().preparse(input);
+ }
+
+ if (moment.isMoment(input)) {
+ config = extend({}, input);
+ config._d = new Date(+input._d);
+ } else if (format) {
+ if (isArray(format)) {
+ makeDateFromStringAndArray(config);
+ } else {
+ makeDateFromStringAndFormat(config);
+ }
+ } else {
+ makeDateFromInput(config);
+ }
+
+ return new Moment(config);
+ }
+
+ moment = function (input, format, lang) {
+ return makeMoment({
+ _i : input,
+ _f : format,
+ _l : lang,
+ _isUTC : false
+ });
+ };
+
+ // creating with utc
+ moment.utc = function (input, format, lang) {
+ return makeMoment({
+ _useUTC : true,
+ _isUTC : true,
+ _l : lang,
+ _i : input,
+ _f : format
+ });
+ };
+
+ // creating with unix timestamp (in seconds)
+ moment.unix = function (input) {
+ return moment(input * 1000);
+ };
+
+ // duration
+ moment.duration = function (input, key) {
+ var isDuration = moment.isDuration(input),
+ isNumber = (typeof input === 'number'),
+ duration = (isDuration ? input._data : (isNumber ? {} : input)),
+ ret;
+
+ if (isNumber) {
+ if (key) {
+ duration[key] = input;
+ } else {
+ duration.milliseconds = input;
+ }
+ }
+
+ ret = new Duration(duration);
+
+ if (isDuration && input.hasOwnProperty('_lang')) {
+ ret._lang = input._lang;
+ }
+
+ return ret;
+ };
+
+ // version number
+ moment.version = VERSION;
+
+ // default format
+ moment.defaultFormat = isoFormat;
+
+ // This function will load languages and then set the global language. If
+ // no arguments are passed in, it will simply return the current global
+ // language key.
+ moment.lang = function (key, values) {
+ var i;
+
+ if (!key) {
+ return moment.fn._lang._abbr;
+ }
+ if (values) {
+ loadLang(key, values);
+ } else if (!languages[key]) {
+ getLangDefinition(key);
+ }
+ moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key);
+ };
+
+ // returns language data
+ moment.langData = function (key) {
+ if (key && key._lang && key._lang._abbr) {
+ key = key._lang._abbr;
+ }
+ return getLangDefinition(key);
+ };
+
+ // compare moment object
+ moment.isMoment = function (obj) {
+ return obj instanceof Moment;
+ };
+
+ // for typechecking Duration objects
+ moment.isDuration = function (obj) {
+ return obj instanceof Duration;
+ };
+
+
+ /************************************
+ Moment Prototype
+ ************************************/
+
+
+ moment.fn = Moment.prototype = {
+
+ clone : function () {
+ return moment(this);
+ },
+
+ valueOf : function () {
+ return +this._d;
+ },
+
+ unix : function () {
+ return Math.floor(+this._d / 1000);
+ },
+
+ toString : function () {
+ return this.format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
+ },
+
+ toDate : function () {
+ return this._d;
+ },
+
+ toJSON : function () {
+ return moment.utc(this).format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
+ },
+
+ toArray : function () {
+ var m = this;
+ return [
+ m.year(),
+ m.month(),
+ m.date(),
+ m.hours(),
+ m.minutes(),
+ m.seconds(),
+ m.milliseconds()
+ ];
+ },
+
+ isValid : function () {
+ if (this._isValid == null) {
+ if (this._a) {
+ this._isValid = !compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray());
+ } else {
+ this._isValid = !isNaN(this._d.getTime());
+ }
+ }
+ return !!this._isValid;
+ },
+
+ utc : function () {
+ this._isUTC = true;
+ return this;
+ },
+
+ local : function () {
+ this._isUTC = false;
+ return this;
+ },
+
+ format : function (inputString) {
+ var output = formatMoment(this, inputString || moment.defaultFormat);
+ return this.lang().postformat(output);
+ },
+
+ add : function (input, val) {
+ var dur;
+ // switch args to support add('s', 1) and add(1, 's')
+ if (typeof input === 'string') {
+ dur = moment.duration(+val, input);
+ } else {
+ dur = moment.duration(input, val);
+ }
+ addOrSubtractDurationFromMoment(this, dur, 1);
+ return this;
+ },
+
+ subtract : function (input, val) {
+ var dur;
+ // switch args to support subtract('s', 1) and subtract(1, 's')
+ if (typeof input === 'string') {
+ dur = moment.duration(+val, input);
+ } else {
+ dur = moment.duration(input, val);
+ }
+ addOrSubtractDurationFromMoment(this, dur, -1);
+ return this;
+ },
+
+ diff : function (input, units, asFloat) {
+ var that = this._isUTC ? moment(input).utc() : moment(input).local(),
+ zoneDiff = (this.zone() - that.zone()) * 6e4,
+ diff, output;
+
+ if (units) {
+ // standardize on singular form
+ units = units.replace(/s$/, '');
+ }
+
+ if (units === 'year' || units === 'month') {
+ diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
+ output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
+ output += ((this - moment(this).startOf('month')) - (that - moment(that).startOf('month'))) / diff;
+ if (units === 'year') {
+ output = output / 12;
+ }
+ } else {
+ diff = (this - that) - zoneDiff;
+ output = units === 'second' ? diff / 1e3 : // 1000
+ units === 'minute' ? diff / 6e4 : // 1000 * 60
+ units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
+ units === 'day' ? diff / 864e5 : // 1000 * 60 * 60 * 24
+ units === 'week' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
+ diff;
+ }
+ return asFloat ? output : absRound(output);
+ },
+
+ from : function (time, withoutSuffix) {
+ return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
+ },
+
+ fromNow : function (withoutSuffix) {
+ return this.from(moment(), withoutSuffix);
+ },
+
+ calendar : function () {
+ var diff = this.diff(moment().startOf('day'), 'days', true),
+ format = diff < -6 ? 'sameElse' :
+ diff < -1 ? 'lastWeek' :
+ diff < 0 ? 'lastDay' :
+ diff < 1 ? 'sameDay' :
+ diff < 2 ? 'nextDay' :
+ diff < 7 ? 'nextWeek' : 'sameElse';
+ return this.format(this.lang().calendar(format, this));
+ },
+
+ isLeapYear : function () {
+ var year = this.year();
+ return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
+ },
+
+ isDST : function () {
+ return (this.zone() < moment([this.year()]).zone() ||
+ this.zone() < moment([this.year(), 5]).zone());
+ },
+
+ day : function (input) {
+ var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
+ return input == null ? day :
+ this.add({ d : input - day });
+ },
+
+ startOf: function (units) {
+ units = units.replace(/s$/, '');
+ // the following switch intentionally omits break keywords
+ // to utilize falling through the cases.
+ switch (units) {
+ case 'year':
+ this.month(0);
+ /* falls through */
+ case 'month':
+ this.date(1);
+ /* falls through */
+ case 'week':
+ case 'day':
+ this.hours(0);
+ /* falls through */
+ case 'hour':
+ this.minutes(0);
+ /* falls through */
+ case 'minute':
+ this.seconds(0);
+ /* falls through */
+ case 'second':
+ this.milliseconds(0);
+ /* falls through */
+ }
+
+ // weeks are a special case
+ if (units === 'week') {
+ this.day(0);
+ }
+
+ return this;
+ },
+
+ endOf: function (units) {
+ return this.startOf(units).add(units.replace(/s?$/, 's'), 1).subtract('ms', 1);
+ },
+
+ isAfter: function (input, units) {
+ units = typeof units !== 'undefined' ? units : 'millisecond';
+ return +this.clone().startOf(units) > +moment(input).startOf(units);
+ },
+
+ isBefore: function (input, units) {
+ units = typeof units !== 'undefined' ? units : 'millisecond';
+ return +this.clone().startOf(units) < +moment(input).startOf(units);
+ },
+
+ isSame: function (input, units) {
+ units = typeof units !== 'undefined' ? units : 'millisecond';
+ return +this.clone().startOf(units) === +moment(input).startOf(units);
+ },
+
+ zone : function () {
+ return this._isUTC ? 0 : this._d.getTimezoneOffset();
+ },
+
+ daysInMonth : function () {
+ return moment.utc([this.year(), this.month() + 1, 0]).date();
+ },
+
+ dayOfYear : function (input) {
+ var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
+ return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
+ },
+
+ isoWeek : function (input) {
+ var week = weekOfYear(this, 1, 4);
+ return input == null ? week : this.add("d", (input - week) * 7);
+ },
+
+ week : function (input) {
+ var week = this.lang().week(this);
+ return input == null ? week : this.add("d", (input - week) * 7);
+ },
+
+ // If passed a language key, it will set the language for this
+ // instance. Otherwise, it will return the language configuration
+ // variables for this instance.
+ lang : function (key) {
+ if (key === undefined) {
+ return this._lang;
+ } else {
+ this._lang = getLangDefinition(key);
+ return this;
+ }
+ }
+ };
+
+ // helper for adding shortcuts
+ function makeGetterAndSetter(name, key) {
+ moment.fn[name] = moment.fn[name + 's'] = function (input) {
+ var utc = this._isUTC ? 'UTC' : '';
+ if (input != null) {
+ this._d['set' + utc + key](input);
+ return this;
+ } else {
+ return this._d['get' + utc + key]();
+ }
+ };
+ }
+
+ // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
+ for (i = 0; i < proxyGettersAndSetters.length; i ++) {
+ makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]);
+ }
+
+ // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
+ makeGetterAndSetter('year', 'FullYear');
+
+ // add plural methods
+ moment.fn.days = moment.fn.day;
+ moment.fn.weeks = moment.fn.week;
+ moment.fn.isoWeeks = moment.fn.isoWeek;
+
+ /************************************
+ Duration Prototype
+ ************************************/
+
+
+ moment.duration.fn = Duration.prototype = {
+ weeks : function () {
+ return absRound(this.days() / 7);
+ },
+
+ valueOf : function () {
+ return this._milliseconds +
+ this._days * 864e5 +
+ this._months * 2592e6;
+ },
+
+ humanize : function (withSuffix) {
+ var difference = +this,
+ output = relativeTime(difference, !withSuffix, this.lang());
+
+ if (withSuffix) {
+ output = this.lang().pastFuture(difference, output);
+ }
+
+ return this.lang().postformat(output);
+ },
+
+ lang : moment.fn.lang
+ };
+
+ function makeDurationGetter(name) {
+ moment.duration.fn[name] = function () {
+ return this._data[name];
+ };
+ }
+
+ function makeDurationAsGetter(name, factor) {
+ moment.duration.fn['as' + name] = function () {
+ return +this / factor;
+ };
+ }
+
+ for (i in unitMillisecondFactors) {
+ if (unitMillisecondFactors.hasOwnProperty(i)) {
+ makeDurationAsGetter(i, unitMillisecondFactors[i]);
+ makeDurationGetter(i.toLowerCase());
+ }
+ }
+
+ makeDurationAsGetter('Weeks', 6048e5);
+
+
+ /************************************
+ Default Lang
+ ************************************/
+
+
+ // Set default language, other languages will inherit from English.
+ moment.lang('en', {
+ ordinal : function (number) {
+ var b = number % 10,
+ output = (~~ (number % 100 / 10) === 1) ? 'th' :
+ (b === 1) ? 'st' :
+ (b === 2) ? 'nd' :
+ (b === 3) ? 'rd' : 'th';
+ return number + output;
+ }
+ });
+
+
+ /************************************
+ Exposing Moment
+ ************************************/
+
+
+ // CommonJS module is defined
+ if (hasModule) {
+ module.exports = moment;
+ }
+ /*global ender:false */
+ if (typeof ender === 'undefined') {
+ // here, `this` means `window` in the browser, or `global` on the server
+ // add `moment` as a global object via a string identifier,
+ // for Closure Compiler "advanced" mode
+ this['moment'] = moment;
+ }
+ /*global define:false */
+ if (typeof define === "function" && define.amd) {
+ define("moment", [], function () {
+ return moment;
+ });
+ }
+}).call(this);