2 //! version : 2.4.0 (ff32605)
3 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
7 (function (undefined) {
9 /************************************
11 ************************************/
27 // internal storage for language config files
31 hasModule
= (typeof module
!== 'undefined' && module
.exports
&& typeof require
!== 'undefined'),
33 // ASP.NET json date format regex
34 aspNetJsonRegex
= /^\/?Date\((\-?\d+)/i,
35 aspNetTimeSpanJsonRegex
= /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/,
37 // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html
38 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere
39 isoDurationRegex
= /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/,
42 formattingTokens
= /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g,
43 localFormattingTokens
= /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
45 // parsing token regexes
46 parseTokenOneOrTwoDigits
= /\d\d?/, // 0 - 99
47 parseTokenOneToThreeDigits
= /\d{1,3}/, // 0 - 999
48 parseTokenThreeDigits
= /\d{3}/, // 000 - 999
49 parseTokenFourDigits
= /\d{1,4}/, // 0 - 9999
50 parseTokenSixDigits
= /[+\-]?\d{1,6}/, // -999,999 - 999,999
51 parseTokenDigits
= /\d+/, // nonzero number of digits
52 parseTokenWord
= /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic.
53 parseTokenTimezone
= /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
54 parseTokenT
= /T/i, // T (ISO separator
)
55 parseTokenTimestampMs
= /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
57 // preliminary iso regex
58 // 0000-00-00 0000-W00 or 0000-W00-0 + T + 00 or 00:00 or 00:00:00 or 00:00:00.000 + +00:00 or +0000)
59 isoRegex
= /^\s*\d{4}-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d:?\d\d|Z)?)?$/,
61 isoFormat
= 'YYYY-MM-DDTHH:mm:ssZ',
70 // iso time formats and regexes
72 ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
73 ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
74 ['HH:mm', /(T| )\d\d:\d\d/],
78 // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
79 parseTimezoneChunker
= /([\+\-]|\d\d)/gi,
81 // getter and setter names
82 proxyGettersAndSetters
= 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
83 unitMillisecondFactors
= {
112 dayofyear
: 'dayOfYear',
113 isoweekday
: 'isoWeekday',
115 weekyear
: 'weekYear',
116 isoweekyear
: 'isoWeekYear'
119 // format function strings
120 formatFunctions
= {},
122 // tokens to ordinalize and pad
123 ordinalizeTokens
= 'DDD w W M D d'.split(' '),
124 paddedTokens
= 'M D H h m s w W'.split(' '),
126 formatTokenFunctions
= {
128 return this.month() + 1;
130 MMM : function (format
) {
131 return this.lang().monthsShort(this, format
);
133 MMMM : function (format
) {
134 return this.lang().months(this, format
);
140 return this.dayOfYear();
145 dd : function (format
) {
146 return this.lang().weekdaysMin(this, format
);
148 ddd : function (format
) {
149 return this.lang().weekdaysShort(this, format
);
151 dddd : function (format
) {
152 return this.lang().weekdays(this, format
);
158 return this.isoWeek();
161 return leftZeroFill(this.year() % 100, 2);
164 return leftZeroFill(this.year(), 4);
166 YYYYY : function () {
167 return leftZeroFill(this.year(), 5);
170 return leftZeroFill(this.weekYear() % 100, 2);
173 return this.weekYear();
175 ggggg : function () {
176 return leftZeroFill(this.weekYear(), 5);
179 return leftZeroFill(this.isoWeekYear() % 100, 2);
182 return this.isoWeekYear();
184 GGGGG : function () {
185 return leftZeroFill(this.isoWeekYear(), 5);
188 return this.weekday();
191 return this.isoWeekday();
194 return this.lang().meridiem(this.hours(), this.minutes(), true);
197 return this.lang().meridiem(this.hours(), this.minutes(), false);
203 return this.hours() % 12 || 12;
206 return this.minutes();
209 return this.seconds();
212 return toInt(this.milliseconds() / 100);
215 return leftZeroFill(toInt(this.milliseconds() / 10), 2);
218 return leftZeroFill(this.milliseconds(), 3);
221 return leftZeroFill(this.milliseconds(), 3);
224 var a
= -this.zone(),
230 return b
+ leftZeroFill(toInt(a
/ 60), 2) + ":" + leftZeroFill(toInt(a
) % 60, 2);
233 var a
= -this.zone(),
239 return b
+ leftZeroFill(toInt(10 * a
/ 6), 4);
242 return this.zoneAbbr();
245 return this.zoneName();
252 lists
= ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
254 function padToken(func
, count
) {
255 return function (a
) {
256 return leftZeroFill(func
.call(this, a
), count
);
259 function ordinalizeToken(func
, period
) {
260 return function (a
) {
261 return this.lang().ordinal(func
.call(this, a
), period
);
265 while (ordinalizeTokens
.length
) {
266 i
= ordinalizeTokens
.pop();
267 formatTokenFunctions
[i
+ 'o'] = ordinalizeToken(formatTokenFunctions
[i
], i
);
269 while (paddedTokens
.length
) {
270 i
= paddedTokens
.pop();
271 formatTokenFunctions
[i
+ i
] = padToken(formatTokenFunctions
[i
], 2);
273 formatTokenFunctions
.DDDD
= padToken(formatTokenFunctions
.DDD
, 3);
276 /************************************
278 ************************************/
280 function Language() {
284 // Moment prototype object
285 function Moment(config
) {
286 checkOverflow(config
);
287 extend(this, config
);
290 // Duration Constructor
291 function Duration(duration
) {
292 var normalizedInput
= normalizeObjectUnits(duration
),
293 years
= normalizedInput
.year
|| 0,
294 months
= normalizedInput
.month
|| 0,
295 weeks
= normalizedInput
.week
|| 0,
296 days
= normalizedInput
.day
|| 0,
297 hours
= normalizedInput
.hour
|| 0,
298 minutes
= normalizedInput
.minute
|| 0,
299 seconds
= normalizedInput
.second
|| 0,
300 milliseconds
= normalizedInput
.millisecond
|| 0;
302 // representation for dateAddRemove
303 this._milliseconds
= +milliseconds
+
304 seconds
* 1e3
+ // 1000
305 minutes
* 6e4
+ // 1000 * 60
306 hours
* 36e5
; // 1000 * 60 * 60
307 // Because of dateAddRemove treats 24 hours as different from a
308 // day when working around DST, we need to store them separately
311 // It is impossible translate months into days without knowing
312 // which months you are are talking about, so we have to store
314 this._months
= +months
+
322 /************************************
324 ************************************/
327 function extend(a
, b
) {
329 if (b
.hasOwnProperty(i
)) {
334 if (b
.hasOwnProperty("toString")) {
335 a
.toString
= b
.toString
;
338 if (b
.hasOwnProperty("valueOf")) {
339 a
.valueOf
= b
.valueOf
;
345 function absRound(number
) {
347 return Math
.ceil(number
);
349 return Math
.floor(number
);
353 // left zero fill a number
354 // see http://jsperf.com/left-zero-filling for performance comparison
355 function leftZeroFill(number
, targetLength
) {
356 var output
= number
+ '';
357 while (output
.length
< targetLength
) {
358 output
= '0' + output
;
363 // helper function for _.addTime and _.subtractTime
364 function addOrSubtractDurationFromMoment(mom
, duration
, isAdding
, ignoreUpdateOffset
) {
365 var milliseconds
= duration
._milliseconds
,
366 days
= duration
._days
,
367 months
= duration
._months
,
372 mom
._d
.setTime(+mom
._d
+ milliseconds
* isAdding
);
374 // store the minutes and hours so we can restore them
375 if (days
|| months
) {
376 minutes
= mom
.minute();
380 mom
.date(mom
.date() + days
* isAdding
);
383 mom
.month(mom
.month() + months
* isAdding
);
385 if (milliseconds
&& !ignoreUpdateOffset
) {
386 moment
.updateOffset(mom
);
388 // restore the minutes and hours after possibly changing dst
389 if (days
|| months
) {
395 // check if is an array
396 function isArray(input
) {
397 return Object
.prototype.toString
.call(input
) === '[object Array]';
400 function isDate(input
) {
401 return Object
.prototype.toString
.call(input
) === '[object Date]' ||
402 input
instanceof Date
;
405 // compare two arrays, return the number of differences
406 function compareArrays(array1
, array2
, dontConvert
) {
407 var len
= Math
.min(array1
.length
, array2
.length
),
408 lengthDiff
= Math
.abs(array1
.length
- array2
.length
),
411 for (i
= 0; i
< len
; i
++) {
412 if ((dontConvert
&& array1
[i
] !== array2
[i
]) ||
413 (!dontConvert
&& toInt(array1
[i
]) !== toInt(array2
[i
]))) {
417 return diffs
+ lengthDiff
;
420 function normalizeUnits(units
) {
422 var lowered
= units
.toLowerCase().replace(/(.)s$/, '$1');
423 units
= unitAliases
[units
] || camelFunctions
[lowered
] || lowered
;
428 function normalizeObjectUnits(inputObject
) {
429 var normalizedInput
= {},
434 for (prop
in inputObject
) {
435 if (inputObject
.hasOwnProperty(prop
)) {
436 normalizedProp
= normalizeUnits(prop
);
437 if (normalizedProp
) {
438 normalizedInput
[normalizedProp
] = inputObject
[prop
];
443 return normalizedInput
;
446 function makeList(field
) {
449 if (field
.indexOf('week') === 0) {
453 else if (field
.indexOf('month') === 0) {
461 moment
[field
] = function (format
, index
) {
463 method
= moment
.fn
._lang
[field
],
466 if (typeof format
=== 'number') {
471 getter = function (i
) {
472 var m
= moment().utc().set(setter
, i
);
473 return method
.call(moment
.fn
._lang
, m
, format
|| '');
477 return getter(index
);
480 for (i
= 0; i
< count
; i
++) {
481 results
.push(getter(i
));
488 function toInt(argumentForCoercion
) {
489 var coercedNumber
= +argumentForCoercion
,
492 if (coercedNumber
!== 0 && isFinite(coercedNumber
)) {
493 if (coercedNumber
>= 0) {
494 value
= Math
.floor(coercedNumber
);
496 value
= Math
.ceil(coercedNumber
);
503 function daysInMonth(year
, month
) {
504 return new Date(Date
.UTC(year
, month
+ 1, 0)).getUTCDate();
507 function daysInYear(year
) {
508 return isLeapYear(year
) ? 366 : 365;
511 function isLeapYear(year
) {
512 return (year
% 4 === 0 && year
% 100 !== 0) || year
% 400 === 0;
515 function checkOverflow(m
) {
517 if (m
._a
&& m
._pf
.overflow
=== -2) {
519 m
._a
[MONTH
] < 0 || m
._a
[MONTH
] > 11 ? MONTH
:
520 m
._a
[DATE
] < 1 || m
._a
[DATE
] > daysInMonth(m
._a
[YEAR
], m
._a
[MONTH
]) ? DATE
:
521 m
._a
[HOUR
] < 0 || m
._a
[HOUR
] > 23 ? HOUR
:
522 m
._a
[MINUTE
] < 0 || m
._a
[MINUTE
] > 59 ? MINUTE
:
523 m
._a
[SECOND
] < 0 || m
._a
[SECOND
] > 59 ? SECOND
:
524 m
._a
[MILLISECOND
] < 0 || m
._a
[MILLISECOND
] > 999 ? MILLISECOND
:
527 if (m
._pf
._overflowDayOfYear
&& (overflow
< YEAR
|| overflow
> DATE
)) {
531 m
._pf
.overflow
= overflow
;
535 function initializeParsingFlags(config
) {
544 invalidFormat
: false,
545 userInvalidated
: false,
550 function isValid(m
) {
551 if (m
._isValid
== null) {
552 m
._isValid
= !isNaN(m
._d
.getTime()) &&
553 m
._pf
.overflow
< 0 &&
555 !m
._pf
.invalidMonth
&&
557 !m
._pf
.invalidFormat
&&
558 !m
._pf
.userInvalidated
;
561 m
._isValid
= m
._isValid
&&
562 m
._pf
.charsLeftOver
=== 0 &&
563 m
._pf
.unusedTokens
.length
=== 0;
569 function normalizeLanguage(key
) {
570 return key
? key
.toLowerCase().replace('_', '-') : key
;
573 /************************************
575 ************************************/
578 extend(Language
.prototype, {
580 set : function (config
) {
584 if (typeof prop
=== 'function') {
587 this['_' + i
] = prop
;
592 _months
: "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
593 months : function (m
) {
594 return this._months
[m
.month()];
597 _monthsShort
: "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
598 monthsShort : function (m
) {
599 return this._monthsShort
[m
.month()];
602 monthsParse : function (monthName
) {
605 if (!this._monthsParse
) {
606 this._monthsParse
= [];
609 for (i
= 0; i
< 12; i
++) {
610 // make the regex if we don't have it already
611 if (!this._monthsParse
[i
]) {
612 mom
= moment
.utc([2000, i
]);
613 regex
= '^' + this.months(mom
, '') + '|^' + this.monthsShort(mom
, '');
614 this._monthsParse
[i
] = new RegExp(regex
.replace('.', ''), 'i');
617 if (this._monthsParse
[i
].test(monthName
)) {
623 _weekdays
: "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
624 weekdays : function (m
) {
625 return this._weekdays
[m
.day()];
628 _weekdaysShort
: "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
629 weekdaysShort : function (m
) {
630 return this._weekdaysShort
[m
.day()];
633 _weekdaysMin
: "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
634 weekdaysMin : function (m
) {
635 return this._weekdaysMin
[m
.day()];
638 weekdaysParse : function (weekdayName
) {
641 if (!this._weekdaysParse
) {
642 this._weekdaysParse
= [];
645 for (i
= 0; i
< 7; i
++) {
646 // make the regex if we don't have it already
647 if (!this._weekdaysParse
[i
]) {
648 mom
= moment([2000, 1]).day(i
);
649 regex
= '^' + this.weekdays(mom
, '') + '|^' + this.weekdaysShort(mom
, '') + '|^' + this.weekdaysMin(mom
, '');
650 this._weekdaysParse
[i
] = new RegExp(regex
.replace('.', ''), 'i');
653 if (this._weekdaysParse
[i
].test(weekdayName
)) {
663 LLL
: "MMMM D YYYY LT",
664 LLLL
: "dddd, MMMM D YYYY LT"
666 longDateFormat : function (key
) {
667 var output
= this._longDateFormat
[key
];
668 if (!output
&& this._longDateFormat
[key
.toUpperCase()]) {
669 output
= this._longDateFormat
[key
.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val
) {
672 this._longDateFormat
[key
] = output
;
677 isPM : function (input
) {
678 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays
679 // Using charAt should be more compatible.
680 return ((input
+ '').toLowerCase().charAt(0) === 'p');
683 _meridiemParse
: /[ap]\.?m?\.?/i,
684 meridiem : function (hours
, minutes
, isLower
) {
686 return isLower
? 'pm' : 'PM';
688 return isLower
? 'am' : 'AM';
693 sameDay
: '[Today at] LT',
694 nextDay
: '[Tomorrow at] LT',
695 nextWeek
: 'dddd [at] LT',
696 lastDay
: '[Yesterday at] LT',
697 lastWeek
: '[Last] dddd [at] LT',
700 calendar : function (key
, mom
) {
701 var output
= this._calendar
[key
];
702 return typeof output
=== 'function' ? output
.apply(mom
) : output
;
720 relativeTime : function (number
, withoutSuffix
, string
, isFuture
) {
721 var output
= this._relativeTime
[string
];
722 return (typeof output
=== 'function') ?
723 output(number
, withoutSuffix
, string
, isFuture
) :
724 output
.replace(/%d/i, number
);
726 pastFuture : function (diff
, output
) {
727 var format
= this._relativeTime
[diff
> 0 ? 'future' : 'past'];
728 return typeof format
=== 'function' ? format(output
) : format
.replace(/%s/i, output
);
731 ordinal : function (number
) {
732 return this._ordinal
.replace("%d", number
);
736 preparse : function (string
) {
740 postformat : function (string
) {
744 week : function (mom
) {
745 return weekOfYear(mom
, this._week
.dow
, this._week
.doy
).week
;
749 dow
: 0, // Sunday is the first day of the week.
750 doy
: 6 // The week that contains Jan 1st is the first week of the year.
753 _invalidDate
: 'Invalid date',
754 invalidDate: function () {
755 return this._invalidDate
;
759 // Loads a language definition into the `languages` cache. The function
760 // takes a key and optionally values. If not in the browser and no values
761 // are provided, it will load the language file module. As a convenience,
762 // this function also returns the language values.
763 function loadLang(key
, values
) {
765 if (!languages
[key
]) {
766 languages
[key
] = new Language();
768 languages
[key
].set(values
);
769 return languages
[key
];
772 // Remove a language from the `languages` cache. Mostly useful in tests.
773 function unloadLang(key
) {
774 delete languages
[key
];
777 // Determines which language definition to use and returns it.
779 // With no parameters, it will return the global language. If you
780 // pass in a language key, such as 'en', it will return the
781 // definition for 'en', so long as 'en' has already been loaded using
783 function getLangDefinition(key
) {
784 var i
= 0, j
, lang
, next
, split
,
786 if (!languages
[k
] && hasModule
) {
788 require('./lang/' + k
);
795 return moment
.fn
._lang
;
799 //short-circuit everything else
807 //pick the language from the array
808 //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
809 //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
810 while (i
< key
.length
) {
811 split
= normalizeLanguage(key
[i
]).split('-');
813 next
= normalizeLanguage(key
[i
+ 1]);
814 next
= next
? next
.split('-') : null;
816 lang
= get(split
.slice(0, j
).join('-'));
820 if (next
&& next
.length
>= j
&& compareArrays(split
, next
, true) >= j
- 1) {
821 //the next array item is better than a shallower substring of this one
828 return moment
.fn
._lang
;
831 /************************************
833 ************************************/
836 function removeFormattingTokens(input
) {
837 if (input
.match(/\[[\s\S]/)) {
838 return input
.replace(/^\[|\]$/g, "");
840 return input
.replace(/\\/g
, "");
843 function makeFormatFunction(format
) {
844 var array
= format
.match(formattingTokens
), i
, length
;
846 for (i
= 0, length
= array
.length
; i
< length
; i
++) {
847 if (formatTokenFunctions
[array
[i
]]) {
848 array
[i
] = formatTokenFunctions
[array
[i
]];
850 array
[i
] = removeFormattingTokens(array
[i
]);
854 return function (mom
) {
856 for (i
= 0; i
< length
; i
++) {
857 output
+= array
[i
] instanceof Function
? array
[i
].call(mom
, format
) : array
[i
];
863 // format date using native date object
864 function formatMoment(m
, format
) {
867 return m
.lang().invalidDate();
870 format
= expandFormat(format
, m
.lang());
872 if (!formatFunctions
[format
]) {
873 formatFunctions
[format
] = makeFormatFunction(format
);
876 return formatFunctions
[format
](m
);
879 function expandFormat(format
, lang
) {
882 function replaceLongDateFormatTokens(input
) {
883 return lang
.longDateFormat(input
) || input
;
886 localFormattingTokens
.lastIndex
= 0;
887 while (i
>= 0 && localFormattingTokens
.test(format
)) {
888 format
= format
.replace(localFormattingTokens
, replaceLongDateFormatTokens
);
889 localFormattingTokens
.lastIndex
= 0;
897 /************************************
899 ************************************/
902 // get the regex to find the next token
903 function getParseRegexForToken(token
, config
) {
907 return parseTokenThreeDigits
;
911 return parseTokenFourDigits
;
915 return parseTokenSixDigits
;
920 return parseTokenOneToThreeDigits
;
926 return parseTokenWord
;
929 return getLangDefinition(config
._l
)._meridiemParse
;
931 return parseTokenTimestampMs
;
934 return parseTokenTimezone
;
938 return parseTokenDigits
;
961 return parseTokenOneOrTwoDigits
;
963 a
= new RegExp(regexpEscape(unescapeFormat(token
.replace('\\', '')), "i"));
968 function timezoneMinutesFromString(string
) {
969 var tzchunk
= (parseTokenTimezone
.exec(string
) || [])[0],
970 parts
= (tzchunk
+ '').match(parseTimezoneChunker
) || ['-', 0, 0],
971 minutes
= +(parts
[1] * 60) + toInt(parts
[2]);
973 return parts
[0] === '+' ? -minutes
: minutes
;
976 // function to convert string input to date
977 function addTimeToArrayFromToken(token
, input
, config
) {
978 var a
, datePartArray
= config
._a
;
982 case 'M' : // fall through to MM
985 datePartArray
[MONTH
] = toInt(input
) - 1;
988 case 'MMM' : // fall through to MMMM
990 a
= getLangDefinition(config
._l
).monthsParse(input
);
991 // if we didn't find a month name, mark the date as invalid.
993 datePartArray
[MONTH
] = a
;
995 config
._pf
.invalidMonth
= input
;
999 case 'D' : // fall through to DD
1001 if (input
!= null) {
1002 datePartArray
[DATE
] = toInt(input
);
1006 case 'DDD' : // fall through to DDDD
1008 if (input
!= null) {
1009 config
._dayOfYear
= toInt(input
);
1015 datePartArray
[YEAR
] = toInt(input
) + (toInt(input
) > 68 ? 1900 : 2000);
1019 datePartArray
[YEAR
] = toInt(input
);
1022 case 'a' : // fall through to A
1024 config
._isPm
= getLangDefinition(config
._l
).isPM(input
);
1027 case 'H' : // fall through to hh
1028 case 'HH' : // fall through to hh
1029 case 'h' : // fall through to hh
1031 datePartArray
[HOUR
] = toInt(input
);
1034 case 'm' : // fall through to mm
1036 datePartArray
[MINUTE
] = toInt(input
);
1039 case 's' : // fall through to ss
1041 datePartArray
[SECOND
] = toInt(input
);
1048 datePartArray
[MILLISECOND
] = toInt(('0.' + input
) * 1000);
1050 // UNIX TIMESTAMP WITH MS
1052 config
._d
= new Date(parseFloat(input
) * 1000);
1055 case 'Z' : // fall through to ZZ
1057 config
._useUTC
= true;
1058 config
._tzm
= timezoneMinutesFromString(input
);
1070 token
= token
.substr(0, 1);
1077 token
= token
.substr(0, 2);
1079 config
._w
= config
._w
|| {};
1080 config
._w
[token
] = input
;
1086 // convert an array to a date.
1087 // the array should mirror the parameters below
1088 // note: all values past the year are optional and will default to the lowest possible value.
1089 // [year, month, day , hour, minute, second, millisecond]
1090 function dateFromConfig(config
) {
1091 var i
, date
, input
= [], currentDate
,
1092 yearToUse
, fixYear
, w
, temp
, lang
, weekday
, week
;
1098 currentDate
= currentDateArray(config
);
1100 //compute day of the year from weeks and weekdays
1101 if (config
._w
&& config
._a
[DATE
] == null && config
._a
[MONTH
] == null) {
1102 fixYear = function (val
) {
1104 (val
.length
< 3 ? (parseInt(val
, 10) > 68 ? '19' + val
: '20' + val
) : val
) :
1105 (config
._a
[YEAR
] == null ? moment().weekYear() : config
._a
[YEAR
]);
1109 if (w
.GG
!= null || w
.W
!= null || w
.E
!= null) {
1110 temp
= dayOfYearFromWeeks(fixYear(w
.GG
), w
.W
|| 1, w
.E
, 4, 1);
1113 lang
= getLangDefinition(config
._l
);
1114 weekday
= w
.d
!= null ? parseWeekday(w
.d
, lang
) :
1115 (w
.e
!= null ? parseInt(w
.e
, 10) + lang
._week
.dow
: 0);
1117 week
= parseInt(w
.w
, 10) || 1;
1119 //if we're parsing 'd', then the low day numbers may be next week
1120 if (w
.d
!= null && weekday
< lang
._week
.dow
) {
1124 temp
= dayOfYearFromWeeks(fixYear(w
.gg
), week
, weekday
, lang
._week
.doy
, lang
._week
.dow
);
1127 config
._a
[YEAR
] = temp
.year
;
1128 config
._dayOfYear
= temp
.dayOfYear
;
1131 //if the day of the year is set, figure out what it is
1132 if (config
._dayOfYear
) {
1133 yearToUse
= config
._a
[YEAR
] == null ? currentDate
[YEAR
] : config
._a
[YEAR
];
1135 if (config
._dayOfYear
> daysInYear(yearToUse
)) {
1136 config
._pf
._overflowDayOfYear
= true;
1139 date
= makeUTCDate(yearToUse
, 0, config
._dayOfYear
);
1140 config
._a
[MONTH
] = date
.getUTCMonth();
1141 config
._a
[DATE
] = date
.getUTCDate();
1144 // Default to current date.
1145 // * if no year, month, day of month are given, default to today
1146 // * if day of month is given, default month and year
1147 // * if month is given, default only year
1148 // * if year is given, don't default anything
1149 for (i
= 0; i
< 3 && config
._a
[i
] == null; ++i
) {
1150 config
._a
[i
] = input
[i
] = currentDate
[i
];
1153 // Zero out whatever was not defaulted, including time
1154 for (; i
< 7; i
++) {
1155 config
._a
[i
] = input
[i
] = (config
._a
[i
] == null) ? (i
=== 2 ? 1 : 0) : config
._a
[i
];
1158 // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
1159 input
[HOUR
] += toInt((config
._tzm
|| 0) / 60);
1160 input
[MINUTE
] += toInt((config
._tzm
|| 0) % 60);
1162 config
._d
= (config
._useUTC
? makeUTCDate
: makeDate
).apply(null, input
);
1165 function dateFromObject(config
) {
1166 var normalizedInput
;
1172 normalizedInput
= normalizeObjectUnits(config
._i
);
1174 normalizedInput
.year
,
1175 normalizedInput
.month
,
1176 normalizedInput
.day
,
1177 normalizedInput
.hour
,
1178 normalizedInput
.minute
,
1179 normalizedInput
.second
,
1180 normalizedInput
.millisecond
1183 dateFromConfig(config
);
1186 function currentDateArray(config
) {
1187 var now
= new Date();
1188 if (config
._useUTC
) {
1190 now
.getUTCFullYear(),
1195 return [now
.getFullYear(), now
.getMonth(), now
.getDate()];
1199 // date from string and format string
1200 function makeDateFromStringAndFormat(config
) {
1203 config
._pf
.empty
= true;
1205 // This array is used to make a Date, either with `new Date` or `Date.UTC`
1206 var lang
= getLangDefinition(config
._l
),
1207 string
= '' + config
._i
,
1208 i
, parsedInput
, tokens
, token
, skipped
,
1209 stringLength
= string
.length
,
1210 totalParsedInputLength
= 0;
1212 tokens
= expandFormat(config
._f
, lang
).match(formattingTokens
) || [];
1214 for (i
= 0; i
< tokens
.length
; i
++) {
1216 parsedInput
= (getParseRegexForToken(token
, config
).exec(string
) || [])[0];
1218 skipped
= string
.substr(0, string
.indexOf(parsedInput
));
1219 if (skipped
.length
> 0) {
1220 config
._pf
.unusedInput
.push(skipped
);
1222 string
= string
.slice(string
.indexOf(parsedInput
) + parsedInput
.length
);
1223 totalParsedInputLength
+= parsedInput
.length
;
1225 // don't parse if it's not a known token
1226 if (formatTokenFunctions
[token
]) {
1228 config
._pf
.empty
= false;
1231 config
._pf
.unusedTokens
.push(token
);
1233 addTimeToArrayFromToken(token
, parsedInput
, config
);
1235 else if (config
._strict
&& !parsedInput
) {
1236 config
._pf
.unusedTokens
.push(token
);
1240 // add remaining unparsed input length to the string
1241 config
._pf
.charsLeftOver
= stringLength
- totalParsedInputLength
;
1242 if (string
.length
> 0) {
1243 config
._pf
.unusedInput
.push(string
);
1247 if (config
._isPm
&& config
._a
[HOUR
] < 12) {
1248 config
._a
[HOUR
] += 12;
1250 // if is 12 am, change hours to 0
1251 if (config
._isPm
=== false && config
._a
[HOUR
] === 12) {
1252 config
._a
[HOUR
] = 0;
1255 dateFromConfig(config
);
1256 checkOverflow(config
);
1259 function unescapeFormat(s
) {
1260 return s
.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched
, p1
, p2
, p3
, p4
) {
1261 return p1
|| p2
|| p3
|| p4
;
1265 // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript
1266 function regexpEscape(s
) {
1267 return s
.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&');
1270 // date from string and array of format strings
1271 function makeDateFromStringAndArray(config
) {
1279 if (config
._f
.length
=== 0) {
1280 config
._pf
.invalidFormat
= true;
1281 config
._d
= new Date(NaN
);
1285 for (i
= 0; i
< config
._f
.length
; i
++) {
1287 tempConfig
= extend({}, config
);
1288 initializeParsingFlags(tempConfig
);
1289 tempConfig
._f
= config
._f
[i
];
1290 makeDateFromStringAndFormat(tempConfig
);
1292 if (!isValid(tempConfig
)) {
1296 // if there is any input that was not parsed add a penalty for that format
1297 currentScore
+= tempConfig
._pf
.charsLeftOver
;
1300 currentScore
+= tempConfig
._pf
.unusedTokens
.length
* 10;
1302 tempConfig
._pf
.score
= currentScore
;
1304 if (scoreToBeat
== null || currentScore
< scoreToBeat
) {
1305 scoreToBeat
= currentScore
;
1306 bestMoment
= tempConfig
;
1310 extend(config
, bestMoment
|| tempConfig
);
1313 // date from iso format
1314 function makeDateFromString(config
) {
1317 match
= isoRegex
.exec(string
);
1320 config
._pf
.iso
= true;
1321 for (i
= 4; i
> 0; i
--) {
1323 // match[5] should be "T" or undefined
1324 config
._f
= isoDates
[i
- 1] + (match
[6] || " ");
1328 for (i
= 0; i
< 4; i
++) {
1329 if (isoTimes
[i
][1].exec(string
)) {
1330 config
._f
+= isoTimes
[i
][0];
1334 if (parseTokenTimezone
.exec(string
)) {
1337 makeDateFromStringAndFormat(config
);
1340 config
._d
= new Date(string
);
1344 function makeDateFromInput(config
) {
1345 var input
= config
._i
,
1346 matched
= aspNetJsonRegex
.exec(input
);
1348 if (input
=== undefined) {
1349 config
._d
= new Date();
1350 } else if (matched
) {
1351 config
._d
= new Date(+matched
[1]);
1352 } else if (typeof input
=== 'string') {
1353 makeDateFromString(config
);
1354 } else if (isArray(input
)) {
1355 config
._a
= input
.slice(0);
1356 dateFromConfig(config
);
1357 } else if (isDate(input
)) {
1358 config
._d
= new Date(+input
);
1359 } else if (typeof(input
) === 'object') {
1360 dateFromObject(config
);
1362 config
._d
= new Date(input
);
1366 function makeDate(y
, m
, d
, h
, M
, s
, ms
) {
1367 //can't just apply() to create a date:
1368 //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply
1369 var date
= new Date(y
, m
, d
, h
, M
, s
, ms
);
1371 //the date constructor doesn't accept years < 1970
1373 date
.setFullYear(y
);
1378 function makeUTCDate(y
) {
1379 var date
= new Date(Date
.UTC
.apply(null, arguments
));
1381 date
.setUTCFullYear(y
);
1386 function parseWeekday(input
, language
) {
1387 if (typeof input
=== 'string') {
1388 if (!isNaN(input
)) {
1389 input
= parseInt(input
, 10);
1392 input
= language
.weekdaysParse(input
);
1393 if (typeof input
!== 'number') {
1401 /************************************
1403 ************************************/
1406 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize
1407 function substituteTimeAgo(string
, number
, withoutSuffix
, isFuture
, lang
) {
1408 return lang
.relativeTime(number
|| 1, !!withoutSuffix
, string
, isFuture
);
1411 function relativeTime(milliseconds
, withoutSuffix
, lang
) {
1412 var seconds
= round(Math
.abs(milliseconds
) / 1000),
1413 minutes
= round(seconds
/ 60),
1414 hours
= round(minutes
/ 60),
1415 days
= round(hours
/ 24),
1416 years
= round(days
/ 365),
1417 args
= seconds
< 45 && ['s', seconds
] ||
1418 minutes
=== 1 && ['m'] ||
1419 minutes
< 45 && ['mm', minutes
] ||
1420 hours
=== 1 && ['h'] ||
1421 hours
< 22 && ['hh', hours
] ||
1422 days
=== 1 && ['d'] ||
1423 days
<= 25 && ['dd', days
] ||
1424 days
<= 45 && ['M'] ||
1425 days
< 345 && ['MM', round(days
/ 30)] ||
1426 years
=== 1 && ['y'] || ['yy', years
];
1427 args
[2] = withoutSuffix
;
1428 args
[3] = milliseconds
> 0;
1430 return substituteTimeAgo
.apply({}, args
);
1434 /************************************
1436 ************************************/
1439 // firstDayOfWeek 0 = sun, 6 = sat
1440 // the day of the week that starts the week
1441 // (usually sunday or monday)
1442 // firstDayOfWeekOfYear 0 = sun, 6 = sat
1443 // the first week is the week that contains the first
1444 // of this day of the week
1445 // (eg. ISO weeks use thursday (4))
1446 function weekOfYear(mom
, firstDayOfWeek
, firstDayOfWeekOfYear
) {
1447 var end
= firstDayOfWeekOfYear
- firstDayOfWeek
,
1448 daysToDayOfWeek
= firstDayOfWeekOfYear
- mom
.day(),
1452 if (daysToDayOfWeek
> end
) {
1453 daysToDayOfWeek
-= 7;
1456 if (daysToDayOfWeek
< end
- 7) {
1457 daysToDayOfWeek
+= 7;
1460 adjustedMoment
= moment(mom
).add('d', daysToDayOfWeek
);
1462 week
: Math
.ceil(adjustedMoment
.dayOfYear() / 7),
1463 year
: adjustedMoment
.year()
1467 //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday
1468 function dayOfYearFromWeeks(year
, week
, weekday
, firstDayOfWeekOfYear
, firstDayOfWeek
) {
1469 var d
= new Date(Date
.UTC(year
, 0)).getUTCDay(),
1470 daysToAdd
, dayOfYear
;
1472 weekday
= weekday
!= null ? weekday
: firstDayOfWeek
;
1473 daysToAdd
= firstDayOfWeek
- d
+ (d
> firstDayOfWeekOfYear
? 7 : 0);
1474 dayOfYear
= 7 * (week
- 1) + (weekday
- firstDayOfWeek
) + daysToAdd
+ 1;
1477 year
: dayOfYear
> 0 ? year
: year
- 1,
1478 dayOfYear
: dayOfYear
> 0 ? dayOfYear
: daysInYear(year
- 1) + dayOfYear
1482 /************************************
1484 ************************************/
1486 function makeMoment(config
) {
1487 var input
= config
._i
,
1490 if (typeof config
._pf
=== 'undefined') {
1491 initializeParsingFlags(config
);
1494 if (input
=== null) {
1495 return moment
.invalid({nullInput
: true});
1498 if (typeof input
=== 'string') {
1499 config
._i
= input
= getLangDefinition().preparse(input
);
1502 if (moment
.isMoment(input
)) {
1503 config
= extend({}, input
);
1505 config
._d
= new Date(+input
._d
);
1506 } else if (format
) {
1507 if (isArray(format
)) {
1508 makeDateFromStringAndArray(config
);
1510 makeDateFromStringAndFormat(config
);
1513 makeDateFromInput(config
);
1516 return new Moment(config
);
1519 moment = function (input
, format
, lang
, strict
) {
1520 if (typeof(lang
) === "boolean") {
1533 // creating with utc
1534 moment
.utc = function (input
, format
, lang
, strict
) {
1537 if (typeof(lang
) === "boolean") {
1553 // creating with unix timestamp (in seconds)
1554 moment
.unix = function (input
) {
1555 return moment(input
* 1000);
1559 moment
.duration = function (input
, key
) {
1560 var duration
= input
,
1561 // matching against regexp is expensive, do it on demand
1569 if (moment
.isDuration(input
)) {
1571 ms
: input
._milliseconds
,
1575 } else if (typeof input
=== 'number') {
1578 duration
[key
] = input
;
1580 duration
.milliseconds
= input
;
1582 } else if (!!(match
= aspNetTimeSpanJsonRegex
.exec(input
))) {
1583 sign
= (match
[1] === "-") ? -1 : 1;
1586 d
: toInt(match
[DATE
]) * sign
,
1587 h
: toInt(match
[HOUR
]) * sign
,
1588 m
: toInt(match
[MINUTE
]) * sign
,
1589 s
: toInt(match
[SECOND
]) * sign
,
1590 ms
: toInt(match
[MILLISECOND
]) * sign
1592 } else if (!!(match
= isoDurationRegex
.exec(input
))) {
1593 sign
= (match
[1] === "-") ? -1 : 1;
1594 parseIso = function (inp
) {
1595 // We'd normally use ~~inp for this, but unfortunately it also
1596 // converts floats to ints.
1597 // inp may be undefined, so careful calling replace on it.
1598 var res
= inp
&& parseFloat(inp
.replace(',', '.'));
1599 // apply sign while we're at it
1600 return (isNaN(res
) ? 0 : res
) * sign
;
1603 y
: parseIso(match
[2]),
1604 M
: parseIso(match
[3]),
1605 d
: parseIso(match
[4]),
1606 h
: parseIso(match
[5]),
1607 m
: parseIso(match
[6]),
1608 s
: parseIso(match
[7]),
1609 w
: parseIso(match
[8])
1613 ret
= new Duration(duration
);
1615 if (moment
.isDuration(input
) && input
.hasOwnProperty('_lang')) {
1616 ret
._lang
= input
._lang
;
1623 moment
.version
= VERSION
;
1626 moment
.defaultFormat
= isoFormat
;
1628 // This function will be called whenever a moment is mutated.
1629 // It is intended to keep the offset in sync with the timezone.
1630 moment
.updateOffset = function () {};
1632 // This function will load languages and then set the global language. If
1633 // no arguments are passed in, it will simply return the current global
1635 moment
.lang = function (key
, values
) {
1638 return moment
.fn
._lang
._abbr
;
1641 loadLang(normalizeLanguage(key
), values
);
1642 } else if (values
=== null) {
1645 } else if (!languages
[key
]) {
1646 getLangDefinition(key
);
1648 r
= moment
.duration
.fn
._lang
= moment
.fn
._lang
= getLangDefinition(key
);
1652 // returns language data
1653 moment
.langData = function (key
) {
1654 if (key
&& key
._lang
&& key
._lang
._abbr
) {
1655 key
= key
._lang
._abbr
;
1657 return getLangDefinition(key
);
1660 // compare moment object
1661 moment
.isMoment = function (obj
) {
1662 return obj
instanceof Moment
;
1665 // for typechecking Duration objects
1666 moment
.isDuration = function (obj
) {
1667 return obj
instanceof Duration
;
1670 for (i
= lists
.length
- 1; i
>= 0; --i
) {
1674 moment
.normalizeUnits = function (units
) {
1675 return normalizeUnits(units
);
1678 moment
.invalid = function (flags
) {
1679 var m
= moment
.utc(NaN
);
1680 if (flags
!= null) {
1681 extend(m
._pf
, flags
);
1684 m
._pf
.userInvalidated
= true;
1690 moment
.parseZone = function (input
) {
1691 return moment(input
).parseZone();
1694 /************************************
1696 ************************************/
1699 extend(moment
.fn
= Moment
.prototype, {
1701 clone : function () {
1702 return moment(this);
1705 valueOf : function () {
1706 return +this._d
+ ((this._offset
|| 0) * 60000);
1709 unix : function () {
1710 return Math
.floor(+this / 1000);
1713 toString : function () {
1714 return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
1717 toDate : function () {
1718 return this._offset
? new Date(+this) : this._d
;
1721 toISOString : function () {
1722 return formatMoment(moment(this).utc(), 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1725 toArray : function () {
1738 isValid : function () {
1739 return isValid(this);
1742 isDSTShifted : function () {
1745 return this.isValid() && compareArrays(this._a
, (this._isUTC
? moment
.utc(this._a
) : moment(this._a
)).toArray()) > 0;
1751 parsingFlags : function () {
1752 return extend({}, this._pf
);
1755 invalidAt: function () {
1756 return this._pf
.overflow
;
1760 return this.zone(0);
1763 local : function () {
1765 this._isUTC
= false;
1769 format : function (inputString
) {
1770 var output
= formatMoment(this, inputString
|| moment
.defaultFormat
);
1771 return this.lang().postformat(output
);
1774 add : function (input
, val
) {
1776 // switch args to support add('s', 1) and add(1, 's')
1777 if (typeof input
=== 'string') {
1778 dur
= moment
.duration(+val
, input
);
1780 dur
= moment
.duration(input
, val
);
1782 addOrSubtractDurationFromMoment(this, dur
, 1);
1786 subtract : function (input
, val
) {
1788 // switch args to support subtract('s', 1) and subtract(1, 's')
1789 if (typeof input
=== 'string') {
1790 dur
= moment
.duration(+val
, input
);
1792 dur
= moment
.duration(input
, val
);
1794 addOrSubtractDurationFromMoment(this, dur
, -1);
1798 diff : function (input
, units
, asFloat
) {
1799 var that
= this._isUTC
? moment(input
).zone(this._offset
|| 0) : moment(input
).local(),
1800 zoneDiff
= (this.zone() - that
.zone()) * 6e4
,
1803 units
= normalizeUnits(units
);
1805 if (units
=== 'year' || units
=== 'month') {
1806 // average number of days in the months in the given dates
1807 diff
= (this.daysInMonth() + that
.daysInMonth()) * 432e5
; // 24 * 60 * 60 * 1000 / 2
1808 // difference in months
1809 output
= ((this.year() - that
.year()) * 12) + (this.month() - that
.month());
1810 // adjust by taking difference in days, average number of days
1811 // and dst in the given months.
1812 output
+= ((this - moment(this).startOf('month')) -
1813 (that
- moment(that
).startOf('month'))) / diff
;
1814 // same as above but with zones, to negate all dst
1815 output
-= ((this.zone() - moment(this).startOf('month').zone()) -
1816 (that
.zone() - moment(that
).startOf('month').zone())) * 6e4
/ diff
;
1817 if (units
=== 'year') {
1818 output
= output
/ 12;
1821 diff
= (this - that
);
1822 output
= units
=== 'second' ? diff
/ 1e3
: // 1000
1823 units
=== 'minute' ? diff
/ 6e4
: // 1000 * 60
1824 units
=== 'hour' ? diff
/ 36e5
: // 1000 * 60 * 60
1825 units
=== 'day' ? (diff
- zoneDiff
) / 864e5
: // 1000 * 60 * 60 * 24, negate dst
1826 units
=== 'week' ? (diff
- zoneDiff
) / 6048e5
: // 1000 * 60 * 60 * 24 * 7, negate dst
1829 return asFloat
? output
: absRound(output
);
1832 from : function (time
, withoutSuffix
) {
1833 return moment
.duration(this.diff(time
)).lang(this.lang()._abbr
).humanize(!withoutSuffix
);
1836 fromNow : function (withoutSuffix
) {
1837 return this.from(moment(), withoutSuffix
);
1840 calendar : function () {
1841 var diff
= this.diff(moment().zone(this.zone()).startOf('day'), 'days', true),
1842 format
= diff
< -6 ? 'sameElse' :
1843 diff
< -1 ? 'lastWeek' :
1844 diff
< 0 ? 'lastDay' :
1845 diff
< 1 ? 'sameDay' :
1846 diff
< 2 ? 'nextDay' :
1847 diff
< 7 ? 'nextWeek' : 'sameElse';
1848 return this.format(this.lang().calendar(format
, this));
1851 isLeapYear : function () {
1852 return isLeapYear(this.year());
1855 isDST : function () {
1856 return (this.zone() < this.clone().month(0).zone() ||
1857 this.zone() < this.clone().month(5).zone());
1860 day : function (input
) {
1861 var day
= this._isUTC
? this._d
.getUTCDay() : this._d
.getDay();
1862 if (input
!= null) {
1863 input
= parseWeekday(input
, this.lang());
1864 return this.add({ d
: input
- day
});
1870 month : function (input
) {
1871 var utc
= this._isUTC
? 'UTC' : '',
1874 if (input
!= null) {
1875 if (typeof input
=== 'string') {
1876 input
= this.lang().monthsParse(input
);
1877 if (typeof input
!== 'number') {
1882 dayOfMonth
= this.date();
1884 this._d
['set' + utc
+ 'Month'](input
);
1885 this.date(Math
.min(dayOfMonth
, this.daysInMonth()));
1887 moment
.updateOffset(this);
1890 return this._d
['get' + utc
+ 'Month']();
1894 startOf: function (units
) {
1895 units
= normalizeUnits(units
);
1896 // the following switch intentionally omits break keywords
1897 // to utilize falling through the cases.
1917 this.milliseconds(0);
1921 // weeks are a special case
1922 if (units
=== 'week') {
1924 } else if (units
=== 'isoWeek') {
1931 endOf: function (units
) {
1932 units
= normalizeUnits(units
);
1933 return this.startOf(units
).add((units
=== 'isoWeek' ? 'week' : units
), 1).subtract('ms', 1);
1936 isAfter: function (input
, units
) {
1937 units
= typeof units
!== 'undefined' ? units
: 'millisecond';
1938 return +this.clone().startOf(units
) > +moment(input
).startOf(units
);
1941 isBefore: function (input
, units
) {
1942 units
= typeof units
!== 'undefined' ? units
: 'millisecond';
1943 return +this.clone().startOf(units
) < +moment(input
).startOf(units
);
1946 isSame: function (input
, units
) {
1947 units
= typeof units
!== 'undefined' ? units
: 'millisecond';
1948 return +this.clone().startOf(units
) === +moment(input
).startOf(units
);
1951 min: function (other
) {
1952 other
= moment
.apply(null, arguments
);
1953 return other
< this ? this : other
;
1956 max: function (other
) {
1957 other
= moment
.apply(null, arguments
);
1958 return other
> this ? this : other
;
1961 zone : function (input
) {
1962 var offset
= this._offset
|| 0;
1963 if (input
!= null) {
1964 if (typeof input
=== "string") {
1965 input
= timezoneMinutesFromString(input
);
1967 if (Math
.abs(input
) < 16) {
1970 this._offset
= input
;
1972 if (offset
!== input
) {
1973 addOrSubtractDurationFromMoment(this, moment
.duration(offset
- input
, 'm'), 1, true);
1976 return this._isUTC
? offset
: this._d
.getTimezoneOffset();
1981 zoneAbbr : function () {
1982 return this._isUTC
? "UTC" : "";
1985 zoneName : function () {
1986 return this._isUTC
? "Coordinated Universal Time" : "";
1989 parseZone : function () {
1990 if (typeof this._i
=== 'string') {
1996 hasAlignedHourOffset : function (input
) {
2001 input
= moment(input
).zone();
2004 return (this.zone() - input
) % 60 === 0;
2007 daysInMonth : function () {
2008 return daysInMonth(this.year(), this.month());
2011 dayOfYear : function (input
) {
2012 var dayOfYear
= round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5
) + 1;
2013 return input
== null ? dayOfYear
: this.add("d", (input
- dayOfYear
));
2016 weekYear : function (input
) {
2017 var year
= weekOfYear(this, this.lang()._week
.dow
, this.lang()._week
.doy
).year
;
2018 return input
== null ? year
: this.add("y", (input
- year
));
2021 isoWeekYear : function (input
) {
2022 var year
= weekOfYear(this, 1, 4).year
;
2023 return input
== null ? year
: this.add("y", (input
- year
));
2026 week : function (input
) {
2027 var week
= this.lang().week(this);
2028 return input
== null ? week
: this.add("d", (input
- week
) * 7);
2031 isoWeek : function (input
) {
2032 var week
= weekOfYear(this, 1, 4).week
;
2033 return input
== null ? week
: this.add("d", (input
- week
) * 7);
2036 weekday : function (input
) {
2037 var weekday
= (this.day() + 7 - this.lang()._week
.dow
) % 7;
2038 return input
== null ? weekday
: this.add("d", input
- weekday
);
2041 isoWeekday : function (input
) {
2042 // behaves the same as moment#day except
2043 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
2044 // as a setter, sunday should belong to the previous week.
2045 return input
== null ? this.day() || 7 : this.day(this.day() % 7 ? input
: input
- 7);
2048 get : function (units
) {
2049 units
= normalizeUnits(units
);
2050 return this[units
]();
2053 set : function (units
, value
) {
2054 units
= normalizeUnits(units
);
2055 if (typeof this[units
] === 'function') {
2061 // If passed a language key, it will set the language for this
2062 // instance. Otherwise, it will return the language configuration
2063 // variables for this instance.
2064 lang : function (key
) {
2065 if (key
=== undefined) {
2068 this._lang
= getLangDefinition(key
);
2074 // helper for adding shortcuts
2075 function makeGetterAndSetter(name
, key
) {
2076 moment
.fn
[name
] = moment
.fn
[name
+ 's'] = function (input
) {
2077 var utc
= this._isUTC
? 'UTC' : '';
2078 if (input
!= null) {
2079 this._d
['set' + utc
+ key
](input
);
2080 moment
.updateOffset(this);
2083 return this._d
['get' + utc
+ key
]();
2088 // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds)
2089 for (i
= 0; i
< proxyGettersAndSetters
.length
; i
++) {
2090 makeGetterAndSetter(proxyGettersAndSetters
[i
].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters
[i
]);
2093 // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear')
2094 makeGetterAndSetter('year', 'FullYear');
2096 // add plural methods
2097 moment
.fn
.days
= moment
.fn
.day
;
2098 moment
.fn
.months
= moment
.fn
.month
;
2099 moment
.fn
.weeks
= moment
.fn
.week
;
2100 moment
.fn
.isoWeeks
= moment
.fn
.isoWeek
;
2102 // add aliased format methods
2103 moment
.fn
.toJSON
= moment
.fn
.toISOString
;
2105 /************************************
2107 ************************************/
2110 extend(moment
.duration
.fn
= Duration
.prototype, {
2112 _bubble : function () {
2113 var milliseconds
= this._milliseconds
,
2115 months
= this._months
,
2117 seconds
, minutes
, hours
, years
;
2119 // The following code bubbles up values, see the tests for
2120 // examples of what that means.
2121 data
.milliseconds
= milliseconds
% 1000;
2123 seconds
= absRound(milliseconds
/ 1000);
2124 data
.seconds
= seconds
% 60;
2126 minutes
= absRound(seconds
/ 60);
2127 data
.minutes
= minutes
% 60;
2129 hours
= absRound(minutes
/ 60);
2130 data
.hours
= hours
% 24;
2132 days
+= absRound(hours
/ 24);
2133 data
.days
= days
% 30;
2135 months
+= absRound(days
/ 30);
2136 data
.months
= months
% 12;
2138 years
= absRound(months
/ 12);
2142 weeks : function () {
2143 return absRound(this.days() / 7);
2146 valueOf : function () {
2147 return this._milliseconds
+
2148 this._days
* 864e5
+
2149 (this._months
% 12) * 2592e6
+
2150 toInt(this._months
/ 12) * 31536e6
;
2153 humanize : function (withSuffix
) {
2154 var difference
= +this,
2155 output
= relativeTime(difference
, !withSuffix
, this.lang());
2158 output
= this.lang().pastFuture(difference
, output
);
2161 return this.lang().postformat(output
);
2164 add : function (input
, val
) {
2165 // supports only 2.0-style add(1, 's') or add(moment)
2166 var dur
= moment
.duration(input
, val
);
2168 this._milliseconds
+= dur
._milliseconds
;
2169 this._days
+= dur
._days
;
2170 this._months
+= dur
._months
;
2177 subtract : function (input
, val
) {
2178 var dur
= moment
.duration(input
, val
);
2180 this._milliseconds
-= dur
._milliseconds
;
2181 this._days
-= dur
._days
;
2182 this._months
-= dur
._months
;
2189 get : function (units
) {
2190 units
= normalizeUnits(units
);
2191 return this[units
.toLowerCase() + 's']();
2194 as : function (units
) {
2195 units
= normalizeUnits(units
);
2196 return this['as' + units
.charAt(0).toUpperCase() + units
.slice(1) + 's']();
2199 lang
: moment
.fn
.lang
,
2201 toIsoString : function () {
2202 // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
2203 var years
= Math
.abs(this.years()),
2204 months
= Math
.abs(this.months()),
2205 days
= Math
.abs(this.days()),
2206 hours
= Math
.abs(this.hours()),
2207 minutes
= Math
.abs(this.minutes()),
2208 seconds
= Math
.abs(this.seconds() + this.milliseconds() / 1000);
2210 if (!this.asSeconds()) {
2211 // this is the same as C#'s (Noda) and python (isodate)...
2212 // but not other JS (goog.date)
2216 return (this.asSeconds() < 0 ? '-' : '') +
2218 (years
? years
+ 'Y' : '') +
2219 (months
? months
+ 'M' : '') +
2220 (days
? days
+ 'D' : '') +
2221 ((hours
|| minutes
|| seconds
) ? 'T' : '') +
2222 (hours
? hours
+ 'H' : '') +
2223 (minutes
? minutes
+ 'M' : '') +
2224 (seconds
? seconds
+ 'S' : '');
2228 function makeDurationGetter(name
) {
2229 moment
.duration
.fn
[name
] = function () {
2230 return this._data
[name
];
2234 function makeDurationAsGetter(name
, factor
) {
2235 moment
.duration
.fn
['as' + name
] = function () {
2236 return +this / factor
;
2240 for (i
in unitMillisecondFactors
) {
2241 if (unitMillisecondFactors
.hasOwnProperty(i
)) {
2242 makeDurationAsGetter(i
, unitMillisecondFactors
[i
]);
2243 makeDurationGetter(i
.toLowerCase());
2247 makeDurationAsGetter('Weeks', 6048e5
);
2248 moment
.duration
.fn
.asMonths = function () {
2249 return (+this - this.years() * 31536e6
) / 2592e6
+ this.years() * 12;
2253 /************************************
2255 ************************************/
2258 // Set default language, other languages will inherit from English.
2260 ordinal : function (number
) {
2261 var b
= number
% 10,
2262 output
= (toInt(number
% 100 / 10) === 1) ? 'th' :
2265 (b
=== 3) ? 'rd' : 'th';
2266 return number
+ output
;
2270 /* EMBED_LANGUAGES */
2272 /************************************
2274 ************************************/
2276 function makeGlobal(deprecate
) {
2277 var warned
= false, local_moment
= moment
;
2278 /*global ender:false */
2279 if (typeof ender
!== 'undefined') {
2282 // here, `this` means `window` in the browser, or `global` on the server
2283 // add `moment` as a global object via a string identifier,
2284 // for Closure Compiler "advanced" mode
2286 global
.moment = function () {
2287 if (!warned
&& console
&& console
.warn
) {
2290 "Accessing Moment through the global scope is " +
2291 "deprecated, and will be removed in an upcoming " +
2294 return local_moment
.apply(null, arguments
);
2297 global
['moment'] = moment
;
2301 // CommonJS module is defined
2303 module
.exports
= moment
;
2305 } else if (typeof define
=== "function" && define
.amd
) {
2306 define("moment", function (require
, exports
, module
) {
2307 if (module
.config().noGlobal
!== true) {
2308 // If user provided noGlobal, he is aware of global
2309 makeGlobal(module
.config().noGlobal
=== undefined);