7 (function (undefined) {
9 /************************************
11 ************************************/
15 round = Math.round, i,
16 // internal storage for language config files
18 currentLanguage = 'en',
21 hasModule = (typeof module !== 'undefined' && module.exports),
23 // Parameters to check for on the lang config. This list of properties
24 // will be inherited from English if not provided in a language
25 // definition. monthsParse is also a lang config property, but it
26 // cannot be inherited and as such cannot be enumerated here.
27 langConfigProperties = 'months|monthsShort|weekdays|weekdaysShort|weekdaysMin|longDateFormat|calendar|relativeTime|ordinal|meridiem'.split('|'),
29 // ASP.NET json date format regex
30 aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
33 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,
34 localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?)/g,
37 parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
39 // parsing token regexes
40 parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
41 parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
42 parseTokenThreeDigits = /\d{3}/, // 000 - 999
43 parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
44 parseTokenWord = /[0-9a-z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+/i, // any word characters or numbers
45 parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
46 parseTokenT = /T/i, // T (ISO seperator)
48 // preliminary iso regex
49 // 0000-00-00 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000
50 isoRegex = /^\s*\d{4}-\d\d-\d\d(T(\d\d(:\d\d(:\d\d(\.\d\d?\d?)?)?)?)?([\+\-]\d\d:?\d\d)?)?/,
51 isoFormat = 'YYYY-MM-DDTHH:mm:ssZ',
53 // iso time formats and regexes
55 ['HH:mm:ss.S', /T\d\d:\d\d:\d\d\.\d{1,3}/],
56 ['HH:mm:ss', /T\d\d:\d\d:\d\d/],
57 ['HH:mm', /T\d\d:\d\d/],
61 // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
62 parseTimezoneChunker = /([\+\-]|\d\d)/gi,
64 // getter and setter names
65 proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
66 unitMillisecondFactors = {
76 // format function strings
79 // tokens to ordinalize and pad
80 ordinalizeTokens = 'DDD w M D d'.split(' '),
81 paddedTokens = 'M D H h m s w'.split(' '),
84 * moment.fn.format uses new Function() to create an inlined formatting function.
85 * Results are a 3x speed boost
86 * http://jsperf.com/momentjs-cached-format-functions
88 * These strings are appended into a function using replaceFormatTokens and makeFormatFunction
90 formatTokenFunctions = {
93 // t = the current moment being formatted
94 // v = getValueAtKey function
95 // o = language.ordinal function
96 // p = leftZeroFill function
97 // m = language.meridiem value or function
99 return this.month() + 1;
101 MMM : function (format) {
102 return getValueFromArray("monthsShort", this.month(), this, format);
104 MMMM : function (format) {
105 return getValueFromArray("months", this.month(), this, format);
111 var a = new Date(this.year(), this.month(), this.date()),
112 b = new Date(this.year(), 0, 1);
113 return ~~(((a - b) / 864e5) + 1.5);
118 dd : function (format) {
119 return getValueFromArray("weekdaysMin", this.day(), this, format);
121 ddd : function (format) {
122 return getValueFromArray("weekdaysShort", this.day(), this, format);
124 dddd : function (format) {
125 return getValueFromArray("weekdays", this.day(), this, format);
128 var a = new Date(this.year(), this.month(), this.date() - this.day() + 5),
129 b = new Date(a.getFullYear(), 0, 4);
130 return ~~((a - b) / 864e5 / 7 + 1.5);
133 return leftZeroFill(this.year() % 100, 2);
136 return leftZeroFill(this.year(), 4);
139 return this.lang().meridiem(this.hours(), this.minutes(), true);
142 return this.lang().meridiem(this.hours(), this.minutes(), false);
148 return this.hours() % 12 || 12;
151 return this.minutes();
154 return this.seconds();
157 return ~~(this.milliseconds() / 100);
160 return leftZeroFill(~~(this.milliseconds() / 10), 2);
163 return leftZeroFill(this.milliseconds(), 3);
166 var a = -this.zone(),
172 return b + leftZeroFill(~~(a / 60), 2) + ":" + leftZeroFill(~~a % 60, 2);
175 var a = -this.zone(),
181 return b + leftZeroFill(~~(10 * a / 6), 4);
185 function getValueFromArray(key, index, m, format) {
187 return lang[key].call ? lang[key](m, format) : lang[key][index];
190 function padToken(func, count) {
191 return function (a) {
192 return leftZeroFill(func.call(this, a), count);
195 function ordinalizeToken(func) {
196 return function (a) {
197 var b = func.call(this, a);
198 return b + this.lang().ordinal(b);
202 while (ordinalizeTokens.length) {
203 i = ordinalizeTokens.pop();
204 formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
206 while (paddedTokens.length) {
207 i = paddedTokens.pop();
208 formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2);
210 formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
213 /************************************
215 ************************************/
218 // Moment prototype object
219 function Moment(date, isUTC, lang) {
221 this._isUTC = !!isUTC;
222 this._a = date._a || null;
223 this._lang = lang || false;
226 // Duration Constructor
227 function Duration(duration) {
228 var data = this._data = {},
229 years = duration.years || duration.y || 0,
230 months = duration.months || duration.M || 0,
231 weeks = duration.weeks || duration.w || 0,
232 days = duration.days || duration.d || 0,
233 hours = duration.hours || duration.h || 0,
234 minutes = duration.minutes || duration.m || 0,
235 seconds = duration.seconds || duration.s || 0,
236 milliseconds = duration.milliseconds || duration.ms || 0;
238 // representation for dateAddRemove
239 this._milliseconds = milliseconds +
240 seconds * 1e3 + // 1000
241 minutes * 6e4 + // 1000 * 60
242 hours * 36e5; // 1000 * 60 * 60
243 // Because of dateAddRemove treats 24 hours as different from a
244 // day when working around DST, we need to store them separately
247 // It is impossible translate months into days without knowing
248 // which months you are are talking about, so we have to store
250 this._months = months +
253 // The following code bubbles up values, see the tests for
254 // examples of what that means.
255 data.milliseconds = milliseconds % 1000;
256 seconds += absRound(milliseconds / 1000);
258 data.seconds = seconds % 60;
259 minutes += absRound(seconds / 60);
261 data.minutes = minutes % 60;
262 hours += absRound(minutes / 60);
264 data.hours = hours % 24;
265 days += absRound(hours / 24);
268 data.days = days % 30;
270 months += absRound(days / 30);
272 data.months = months % 12;
273 years += absRound(months / 12);
281 /************************************
283 ************************************/
286 function absRound(number) {
288 return Math.ceil(number);
290 return Math.floor(number);
294 // left zero fill a number
295 // see http://jsperf.com/left-zero-filling for performance comparison
296 function leftZeroFill(number, targetLength) {
297 var output = number + '';
298 while (output.length < targetLength) {
299 output = '0' + output;
304 // helper function for _.addTime and _.subtractTime
305 function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
306 var ms = duration._milliseconds,
308 M = duration._months,
312 mom._d.setTime(+mom + ms * isAdding);
315 mom.date(mom.date() + d * isAdding);
318 currentDate = mom.date();
320 .month(mom.month() + M * isAdding)
321 .date(Math.min(currentDate, mom.daysInMonth()));
325 // check if is an array
326 function isArray(input) {
327 return Object.prototype.toString.call(input) === '[object Array]';
330 // compare two arrays, return the number of differences
331 function compareArrays(array1, array2) {
332 var len = Math.min(array1.length, array2.length),
333 lengthDiff = Math.abs(array1.length - array2.length),
336 for (i = 0; i < len; i++) {
337 if (~~array1[i] !== ~~array2[i]) {
341 return diffs + lengthDiff;
344 // convert an array to a date.
345 // the array should mirror the parameters below
346 // note: all values past the year are optional and will default to the lowest possible value.
347 // [year, month, day , hour, minute, second, millisecond]
348 function dateFromArray(input, asUTC, hoursOffset, minutesOffset) {
349 var i, date, forValid = [];
350 for (i = 0; i < 7; i++) {
351 forValid[i] = input[i] = (input[i] == null) ? (i === 2 ? 1 : 0) : input[i];
353 // we store whether we used utc or not in the input array
354 input[7] = forValid[7] = asUTC;
355 // if the parser flagged the input as invalid, we pass the value along
356 if (input[8] != null) {
357 forValid[8] = input[8];
359 // add the offsets to the time to be parsed so that we can have a clean array
360 // for checking isValid
361 input[3] += hoursOffset || 0;
362 input[4] += minutesOffset || 0;
365 date.setUTCFullYear(input[0], input[1], input[2]);
366 date.setUTCHours(input[3], input[4], input[5], input[6]);
368 date.setFullYear(input[0], input[1], input[2]);
369 date.setHours(input[3], input[4], input[5], input[6]);
375 // Loads a language definition into the `languages` cache. The function
376 // takes a key and optionally values. If not in the browser and no values
377 // are provided, it will load the language file module. As a convenience,
378 // this function also returns the language values.
379 function loadLang(key, values) {
383 if (!values && hasModule) {
384 values = require('./lang/' + key);
387 for (i = 0; i < langConfigProperties.length; i++) {
388 // If a language definition does not provide a value, inherit
390 values[langConfigProperties[i]] = values[langConfigProperties[i]] ||
391 languages.en[langConfigProperties[i]];
394 for (i = 0; i < 12; i++) {
395 m = moment([2000, i]);
396 parse[i] = new RegExp('^' + (values.months[i] || values.months(m, '')) +
397 '|^' + (values.monthsShort[i] || values.monthsShort(m, '')).replace('.', ''), 'i');
399 values.monthsParse = values.monthsParse || parse;
401 languages[key] = values;
406 // Determines which language definition to use and returns it.
408 // With no parameters, it will return the global language. If you
409 // pass in a language key, such as 'en', it will return the
410 // definition for 'en', so long as 'en' has already been loaded using
411 // moment.lang. If you pass in a moment or duration instance, it
412 // will decide the language based on that, or default to the global
414 function getLangDefinition(m) {
415 var langKey = (typeof m === 'string') && m ||
419 return langKey ? (languages[langKey] || loadLang(langKey)) : moment;
423 /************************************
425 ************************************/
428 function removeFormattingTokens(input) {
429 if (input.match(/\[.*\]/)) {
430 return input.replace(/^\[|\]$/g, "");
432 return input.replace(/\\/g, "");
435 function makeFormatFunction(format) {
436 var array = format.match(formattingTokens), i, length;
438 for (i = 0, length = array.length; i < length; i++) {
439 if (formatTokenFunctions[array[i]]) {
440 array[i] = formatTokenFunctions[array[i]];
442 array[i] = removeFormattingTokens(array[i]);
446 return function (mom) {
448 for (i = 0; i < length; i++) {
449 output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i];
455 // format date using native date object
456 function formatMoment(m, format) {
459 function replaceLongDateFormatTokens(input) {
460 return m.lang().longDateFormat[input] || input;
463 while (i-- && localFormattingTokens.test(format)) {
464 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens);
467 if (!formatFunctions[format]) {
468 formatFunctions[format] = makeFormatFunction(format);
471 return formatFunctions[format](m);
475 /************************************
477 ************************************/
480 // get the regex to find the next token
481 function getParseRegexForToken(token) {
484 return parseTokenThreeDigits;
486 return parseTokenFourDigits;
491 return parseTokenOneToThreeDigits;
499 return parseTokenWord;
502 return parseTokenTimezone;
519 return parseTokenOneOrTwoDigits;
521 return new RegExp(token.replace('\\', ''));
525 // function to convert string input to date
526 function addTimeToArrayFromToken(token, input, datePartArray, config) {
531 case 'M' : // fall through to MM
533 datePartArray[1] = (input == null) ? 0 : ~~input - 1;
535 case 'MMM' : // fall through to MMMM
537 for (a = 0; a < 12; a++) {
538 if (getLangDefinition().monthsParse[a].test(input)) {
539 datePartArray[1] = a;
544 // if we didn't find a month name, mark the date as invalid.
546 datePartArray[8] = false;
550 case 'D' : // fall through to DDDD
551 case 'DD' : // fall through to DDDD
552 case 'DDD' : // fall through to DDDD
555 datePartArray[2] = ~~input;
560 datePartArray[0] = ~~input + (~~input > 70 ? 1900 : 2000);
563 datePartArray[0] = ~~Math.abs(input);
566 case 'a' : // fall through to A
568 config.isPm = ((input + '').toLowerCase() === 'pm');
571 case 'H' : // fall through to hh
572 case 'HH' : // fall through to hh
573 case 'h' : // fall through to hh
575 datePartArray[3] = ~~input;
578 case 'm' : // fall through to mm
580 datePartArray[4] = ~~input;
583 case 's' : // fall through to ss
585 datePartArray[5] = ~~input;
591 datePartArray[6] = ~~ (('0.' + input) * 1000);
594 case 'Z' : // fall through to ZZ
597 a = (input + '').match(parseTimezoneChunker);
605 if (a && a[0] === '+') {
606 config.tzh = -config.tzh;
607 config.tzm = -config.tzm;
612 // if the input is null, the date is not valid
614 datePartArray[8] = false;
618 // date from string and format string
619 function makeDateFromStringAndFormat(string, format) {
620 // This array is used to make a Date, either with `new Date` or `Date.UTC`
621 // We store some additional data on the array for validation
622 // datePartArray[7] is true if the Date was created with `Date.UTC` and false if created with `new Date`
623 // datePartArray[8] is false if the Date is invalid, and undefined if the validity is unknown.
624 var datePartArray = [0, 0, 1, 0, 0, 0, 0],
626 tzh : 0, // timezone hour offset
627 tzm : 0 // timezone minute offset
629 tokens = format.match(formattingTokens),
632 for (i = 0; i < tokens.length; i++) {
633 parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
635 string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
637 // don't parse if its not a known token
638 if (formatTokenFunctions[tokens[i]]) {
639 addTimeToArrayFromToken(tokens[i], parsedInput, datePartArray, config);
643 if (config.isPm && datePartArray[3] < 12) {
644 datePartArray[3] += 12;
646 // if is 12 am, change hours to 0
647 if (config.isPm === false && datePartArray[3] === 12) {
648 datePartArray[3] = 0;
651 return dateFromArray(datePartArray, config.isUTC, config.tzh, config.tzm);
654 // date from string and array of format strings
655 function makeDateFromStringAndArray(string, formats) {
657 inputParts = string.match(parseMultipleFormatChunker) || [],
663 for (i = 0; i < formats.length; i++) {
664 currentDate = makeDateFromStringAndFormat(string, formats[i]);
665 formattedInputParts = formatMoment(new Moment(currentDate), formats[i]).match(parseMultipleFormatChunker) || [];
666 currentScore = compareArrays(inputParts, formattedInputParts);
667 if (currentScore < scoreToBeat) {
668 scoreToBeat = currentScore;
669 output = currentDate;
675 // date from iso format
676 function makeDateFromString(string) {
677 var format = 'YYYY-MM-DDT',
679 if (isoRegex.exec(string)) {
680 for (i = 0; i < 4; i++) {
681 if (isoTimes[i][1].exec(string)) {
682 format += isoTimes[i][0];
686 return parseTokenTimezone.exec(string) ?
687 makeDateFromStringAndFormat(string, format + ' Z') :
688 makeDateFromStringAndFormat(string, format);
690 return new Date(string);
694 /************************************
696 ************************************/
699 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
700 function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) {
701 var rt = lang.relativeTime[string];
702 return (typeof rt === 'function') ?
703 rt(number || 1, !!withoutSuffix, string, isFuture) :
704 rt.replace(/%d/i, number || 1);
707 function relativeTime(milliseconds, withoutSuffix, lang) {
708 var seconds = round(Math.abs(milliseconds) / 1000),
709 minutes = round(seconds / 60),
710 hours = round(minutes / 60),
711 days = round(hours / 24),
712 years = round(days / 365),
713 args = seconds < 45 && ['s', seconds] ||
714 minutes === 1 && ['m'] ||
715 minutes < 45 && ['mm', minutes] ||
716 hours === 1 && ['h'] ||
717 hours < 22 && ['hh', hours] ||
718 days === 1 && ['d'] ||
719 days <= 25 && ['dd', days] ||
720 days <= 45 && ['M'] ||
721 days < 345 && ['MM', round(days / 30)] ||
722 years === 1 && ['y'] || ['yy', years];
723 args[2] = withoutSuffix;
724 args[3] = milliseconds > 0;
726 return substituteTimeAgo.apply({}, args);
730 /************************************
732 ************************************/
735 moment = function (input, format) {
736 if (input === null || input === '') {
741 // parse Moment object
742 if (moment.isMoment(input)) {
743 return new Moment(new Date(+input._d), input._isUTC, input._lang);
744 // parse string and format
746 if (isArray(format)) {
747 date = makeDateFromStringAndArray(input, format);
749 date = makeDateFromStringAndFormat(input, format);
751 // evaluate it as a JSON-encoded date
753 matched = aspNetJsonRegex.exec(input);
754 date = input === undefined ? new Date() :
755 matched ? new Date(+matched[1]) :
756 input instanceof Date ? input :
757 isArray(input) ? dateFromArray(input) :
758 typeof input === 'string' ? makeDateFromString(input) :
762 return new Moment(date);
766 moment.utc = function (input, format) {
767 if (isArray(input)) {
768 return new Moment(dateFromArray(input, true), true);
770 // if we don't have a timezone, we need to add one to trigger parsing into utc
771 if (typeof input === 'string' && !parseTokenTimezone.exec(input)) {
777 return moment(input, format).utc();
780 // creating with unix timestamp (in seconds)
781 moment.unix = function (input) {
782 return moment(input * 1000);
786 moment.duration = function (input, key) {
787 var isDuration = moment.isDuration(input),
788 isNumber = (typeof input === 'number'),
789 duration = (isDuration ? input._data : (isNumber ? {} : input)),
794 duration[key] = input;
796 duration.milliseconds = input;
800 ret = new Duration(duration);
803 ret._lang = input._lang;
810 // This method is deprecated in favor of the new Duration object. Please
811 // see the moment.duration method.
812 moment.humanizeDuration = function (num, type, withSuffix) {
813 return moment.duration(num, type === true ? null : type).humanize(type === true ? true : withSuffix);
817 moment.version = VERSION;
820 moment.defaultFormat = isoFormat;
822 // This function will load languages and then set the global language. If
823 // no arguments are passed in, it will simply return the current global
825 moment.lang = function (key, values) {
829 return currentLanguage;
831 if (values || !languages[key]) {
832 loadLang(key, values);
834 if (languages[key]) {
835 // deprecated, to get the language definition variables, use the
836 // moment.fn.lang method or the getLangDefinition function.
837 for (i = 0; i < langConfigProperties.length; i++) {
838 moment[langConfigProperties[i]] = languages[key][langConfigProperties[i]];
840 moment.monthsParse = languages[key].monthsParse;
841 currentLanguage = key;
845 // returns language data
846 moment.langData = getLangDefinition;
848 // compare moment object
849 moment.isMoment = function (obj) {
850 return obj instanceof Moment;
853 // for typechecking Duration objects
854 moment.isDuration = function (obj) {
855 return obj instanceof Duration;
858 // Set default language, other languages will inherit from English.
860 months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
861 monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
862 weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
863 weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
864 weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
869 LLL : "MMMM D YYYY LT",
870 LLLL : "dddd, MMMM D YYYY LT"
872 meridiem : function (hours, minutes, isLower) {
874 return isLower ? 'pm' : 'PM';
876 return isLower ? 'am' : 'AM';
880 sameDay : '[Today at] LT',
881 nextDay : '[Tomorrow at] LT',
882 nextWeek : 'dddd [at] LT',
883 lastDay : '[Yesterday at] LT',
884 lastWeek : '[last] dddd [at] LT',
902 ordinal : function (number) {
904 return (~~ (number % 100 / 10) === 1) ? 'th' :
907 (b === 3) ? 'rd' : 'th';
912 /************************************
914 ************************************/
917 moment.fn = Moment.prototype = {
919 clone : function () {
923 valueOf : function () {
928 return Math.floor(+this._d / 1000);
931 toString : function () {
932 return this._d.toString();
935 toDate : function () {
939 toArray : function () {
953 isValid : function () {
955 // if the parser finds that the input is invalid, it sets
956 // the eighth item in the input array to false.
957 if (this._a[8] != null) {
960 return !compareArrays(this._a, (this._a[7] ? moment.utc(this._a) : moment(this._a)).toArray());
962 return !isNaN(this._d.getTime());
970 local : function () {
975 format : function (inputString) {
976 return formatMoment(this, inputString ? inputString : moment.defaultFormat);
979 add : function (input, val) {
980 var dur = val ? moment.duration(+val, input) : moment.duration(input);
981 addOrSubtractDurationFromMoment(this, dur, 1);
985 subtract : function (input, val) {
986 var dur = val ? moment.duration(+val, input) : moment.duration(input);
987 addOrSubtractDurationFromMoment(this, dur, -1);
991 diff : function (input, val, asFloat) {
992 var inputMoment = this._isUTC ? moment(input).utc() : moment(input).local(),
993 zoneDiff = (this.zone() - inputMoment.zone()) * 6e4,
994 diff = this._d - inputMoment._d - zoneDiff,
995 year = this.year() - inputMoment.year(),
996 month = this.month() - inputMoment.month(),
997 date = this.date() - inputMoment.date(),
999 if (val === 'months') {
1000 output = year * 12 + month + date / 30;
1001 } else if (val === 'years') {
1002 output = year + (month + date / 30) / 12;
1004 output = val === 'seconds' ? diff / 1e3 : // 1000
1005 val === 'minutes' ? diff / 6e4 : // 1000 * 60
1006 val === 'hours' ? diff / 36e5 : // 1000 * 60 * 60
1007 val === 'days' ? diff / 864e5 : // 1000 * 60 * 60 * 24
1008 val === 'weeks' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
1011 return asFloat ? output : round(output);
1014 from : function (time, withoutSuffix) {
1015 return moment.duration(this.diff(time)).lang(this._lang).humanize(!withoutSuffix);
1018 fromNow : function (withoutSuffix) {
1019 return this.from(moment(), withoutSuffix);
1022 calendar : function () {
1023 var diff = this.diff(moment().sod(), 'days', true),
1024 calendar = this.lang().calendar,
1025 allElse = calendar.sameElse,
1026 format = diff < -6 ? allElse :
1027 diff < -1 ? calendar.lastWeek :
1028 diff < 0 ? calendar.lastDay :
1029 diff < 1 ? calendar.sameDay :
1030 diff < 2 ? calendar.nextDay :
1031 diff < 7 ? calendar.nextWeek : allElse;
1032 return this.format(typeof format === 'function' ? format.apply(this) : format);
1035 isLeapYear : function () {
1036 var year = this.year();
1037 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0;
1040 isDST : function () {
1041 return (this.zone() < moment([this.year()]).zone() ||
1042 this.zone() < moment([this.year(), 5]).zone());
1045 day : function (input) {
1046 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1047 return input == null ? day :
1048 this.add({ d : input - day });
1051 startOf: function (val) {
1052 // the following switch intentionally omits break keywords
1053 // to utilize falling through the cases.
1054 switch (val.replace(/s$/, '')) {
1071 this.milliseconds(0);
1077 endOf: function (val) {
1078 return this.startOf(val).add(val.replace(/s?$/, 's'), 1).subtract('ms', 1);
1082 return this.clone().startOf('day');
1086 // end of day = start of day plus 1 day, minus 1 millisecond
1087 return this.clone().endOf('day');
1090 zone : function () {
1091 return this._isUTC ? 0 : this._d.getTimezoneOffset();
1094 daysInMonth : function () {
1095 return moment.utc([this.year(), this.month() + 1, 0]).date();
1098 // If passed a language key, it will set the language for this
1099 // instance. Otherwise, it will return the language configuration
1100 // variables for this instance.
1101 lang : function (lang) {
1102 if (lang === undefined) {
1103 return getLangDefinition(this);
1111 // helper for adding shortcuts
1112 function makeGetterAndSetter(name, key) {
1113 moment.fn[name] = function (input) {
1114 var utc = this._isUTC ? 'UTC' : '';
1115 if (input != null) {
1116 this._d['set' + utc + key](input);
1119 return this._d['get' + utc + key]();
1124 // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
1125 for (i = 0; i < proxyGettersAndSetters.length; i ++) {
1126 makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase(), proxyGettersAndSetters[i]);
1129 // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
1130 makeGetterAndSetter('year', 'FullYear');
1133 /************************************
1135 ************************************/
1138 moment.duration.fn = Duration.prototype = {
1139 weeks : function () {
1140 return absRound(this.days() / 7);
1143 valueOf : function () {
1144 return this._milliseconds +
1145 this._days * 864e5 +
1146 this._months * 2592e6;
1149 humanize : function (withSuffix) {
1150 var difference = +this,
1151 rel = this.lang().relativeTime,
1152 output = relativeTime(difference, !withSuffix, this.lang()),
1153 fromNow = difference <= 0 ? rel.past : rel.future;
1156 if (typeof fromNow === 'function') {
1157 output = fromNow(output);
1159 output = fromNow.replace(/%s/i, output);
1166 lang : moment.fn.lang
1169 function makeDurationGetter(name) {
1170 moment.duration.fn[name] = function () {
1171 return this._data[name];
1175 function makeDurationAsGetter(name, factor) {
1176 moment.duration.fn['as' + name] = function () {
1177 return +this / factor;
1181 for (i in unitMillisecondFactors) {
1182 if (unitMillisecondFactors.hasOwnProperty(i)) {
1183 makeDurationAsGetter(i, unitMillisecondFactors[i]);
1184 makeDurationGetter(i.toLowerCase());
1188 makeDurationAsGetter('Weeks', 6048e5);
1191 /************************************
1193 ************************************/
1196 // CommonJS module is defined
1198 module.exports = moment;
1200 /*global ender:false */
1201 if (typeof ender === 'undefined') {
1202 // here, `this` means `window` in the browser, or `global` on the server
1203 // add `moment` as a global object via a string identifier,
1204 // for Closure Compiler "advanced" mode
1205 this['moment'] = moment;
1207 /*global define:false */
1208 if (typeof define === "function" && define.amd) {
1209 define("moment", [], function () {