|
1 //! moment.js |
|
2 |
|
3 ;(function (global, factory) { |
|
4 typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() : |
|
5 typeof define === 'function' && define.amd ? define(factory) : |
|
6 global.moment = factory() |
|
7 }(this, (function () { 'use strict'; |
|
8 |
|
9 var hookCallback; |
|
10 |
|
11 function hooks () { |
|
12 return hookCallback.apply(null, arguments); |
|
13 } |
|
14 |
|
15 // This is done to register the method called with moment() |
|
16 // without creating circular dependencies. |
|
17 function setHookCallback (callback) { |
|
18 hookCallback = callback; |
|
19 } |
|
20 |
|
21 function isArray(input) { |
|
22 return input instanceof Array || Object.prototype.toString.call(input) === '[object Array]'; |
|
23 } |
|
24 |
|
25 function isObject(input) { |
|
26 // IE8 will treat undefined and null as object if it wasn't for |
|
27 // input != null |
|
28 return input != null && Object.prototype.toString.call(input) === '[object Object]'; |
|
29 } |
|
30 |
|
31 function isObjectEmpty(obj) { |
|
32 if (Object.getOwnPropertyNames) { |
|
33 return (Object.getOwnPropertyNames(obj).length === 0); |
|
34 } else { |
|
35 var k; |
|
36 for (k in obj) { |
|
37 if (obj.hasOwnProperty(k)) { |
|
38 return false; |
|
39 } |
|
40 } |
|
41 return true; |
|
42 } |
|
43 } |
|
44 |
|
45 function isUndefined(input) { |
|
46 return input === void 0; |
|
47 } |
|
48 |
|
49 function isNumber(input) { |
|
50 return typeof input === 'number' || Object.prototype.toString.call(input) === '[object Number]'; |
|
51 } |
|
52 |
|
53 function isDate(input) { |
|
54 return input instanceof Date || Object.prototype.toString.call(input) === '[object Date]'; |
|
55 } |
|
56 |
|
57 function map(arr, fn) { |
|
58 var res = [], i; |
|
59 for (i = 0; i < arr.length; ++i) { |
|
60 res.push(fn(arr[i], i)); |
|
61 } |
|
62 return res; |
|
63 } |
|
64 |
|
65 function hasOwnProp(a, b) { |
|
66 return Object.prototype.hasOwnProperty.call(a, b); |
|
67 } |
|
68 |
|
69 function extend(a, b) { |
|
70 for (var i in b) { |
|
71 if (hasOwnProp(b, i)) { |
|
72 a[i] = b[i]; |
|
73 } |
|
74 } |
|
75 |
|
76 if (hasOwnProp(b, 'toString')) { |
|
77 a.toString = b.toString; |
|
78 } |
|
79 |
|
80 if (hasOwnProp(b, 'valueOf')) { |
|
81 a.valueOf = b.valueOf; |
|
82 } |
|
83 |
|
84 return a; |
|
85 } |
|
86 |
|
87 function createUTC (input, format, locale, strict) { |
|
88 return createLocalOrUTC(input, format, locale, strict, true).utc(); |
|
89 } |
|
90 |
|
91 function defaultParsingFlags() { |
|
92 // We need to deep clone this object. |
|
93 return { |
|
94 empty : false, |
|
95 unusedTokens : [], |
|
96 unusedInput : [], |
|
97 overflow : -2, |
|
98 charsLeftOver : 0, |
|
99 nullInput : false, |
|
100 invalidMonth : null, |
|
101 invalidFormat : false, |
|
102 userInvalidated : false, |
|
103 iso : false, |
|
104 parsedDateParts : [], |
|
105 meridiem : null, |
|
106 rfc2822 : false, |
|
107 weekdayMismatch : false |
|
108 }; |
|
109 } |
|
110 |
|
111 function getParsingFlags(m) { |
|
112 if (m._pf == null) { |
|
113 m._pf = defaultParsingFlags(); |
|
114 } |
|
115 return m._pf; |
|
116 } |
|
117 |
|
118 var some; |
|
119 if (Array.prototype.some) { |
|
120 some = Array.prototype.some; |
|
121 } else { |
|
122 some = function (fun) { |
|
123 var t = Object(this); |
|
124 var len = t.length >>> 0; |
|
125 |
|
126 for (var i = 0; i < len; i++) { |
|
127 if (i in t && fun.call(this, t[i], i, t)) { |
|
128 return true; |
|
129 } |
|
130 } |
|
131 |
|
132 return false; |
|
133 }; |
|
134 } |
|
135 |
|
136 function isValid(m) { |
|
137 if (m._isValid == null) { |
|
138 var flags = getParsingFlags(m); |
|
139 var parsedParts = some.call(flags.parsedDateParts, function (i) { |
|
140 return i != null; |
|
141 }); |
|
142 var isNowValid = !isNaN(m._d.getTime()) && |
|
143 flags.overflow < 0 && |
|
144 !flags.empty && |
|
145 !flags.invalidMonth && |
|
146 !flags.invalidWeekday && |
|
147 !flags.weekdayMismatch && |
|
148 !flags.nullInput && |
|
149 !flags.invalidFormat && |
|
150 !flags.userInvalidated && |
|
151 (!flags.meridiem || (flags.meridiem && parsedParts)); |
|
152 |
|
153 if (m._strict) { |
|
154 isNowValid = isNowValid && |
|
155 flags.charsLeftOver === 0 && |
|
156 flags.unusedTokens.length === 0 && |
|
157 flags.bigHour === undefined; |
|
158 } |
|
159 |
|
160 if (Object.isFrozen == null || !Object.isFrozen(m)) { |
|
161 m._isValid = isNowValid; |
|
162 } |
|
163 else { |
|
164 return isNowValid; |
|
165 } |
|
166 } |
|
167 return m._isValid; |
|
168 } |
|
169 |
|
170 function createInvalid (flags) { |
|
171 var m = createUTC(NaN); |
|
172 if (flags != null) { |
|
173 extend(getParsingFlags(m), flags); |
|
174 } |
|
175 else { |
|
176 getParsingFlags(m).userInvalidated = true; |
|
177 } |
|
178 |
|
179 return m; |
|
180 } |
|
181 |
|
182 // Plugins that add properties should also add the key here (null value), |
|
183 // so we can properly clone ourselves. |
|
184 var momentProperties = hooks.momentProperties = []; |
|
185 |
|
186 function copyConfig(to, from) { |
|
187 var i, prop, val; |
|
188 |
|
189 if (!isUndefined(from._isAMomentObject)) { |
|
190 to._isAMomentObject = from._isAMomentObject; |
|
191 } |
|
192 if (!isUndefined(from._i)) { |
|
193 to._i = from._i; |
|
194 } |
|
195 if (!isUndefined(from._f)) { |
|
196 to._f = from._f; |
|
197 } |
|
198 if (!isUndefined(from._l)) { |
|
199 to._l = from._l; |
|
200 } |
|
201 if (!isUndefined(from._strict)) { |
|
202 to._strict = from._strict; |
|
203 } |
|
204 if (!isUndefined(from._tzm)) { |
|
205 to._tzm = from._tzm; |
|
206 } |
|
207 if (!isUndefined(from._isUTC)) { |
|
208 to._isUTC = from._isUTC; |
|
209 } |
|
210 if (!isUndefined(from._offset)) { |
|
211 to._offset = from._offset; |
|
212 } |
|
213 if (!isUndefined(from._pf)) { |
|
214 to._pf = getParsingFlags(from); |
|
215 } |
|
216 if (!isUndefined(from._locale)) { |
|
217 to._locale = from._locale; |
|
218 } |
|
219 |
|
220 if (momentProperties.length > 0) { |
|
221 for (i = 0; i < momentProperties.length; i++) { |
|
222 prop = momentProperties[i]; |
|
223 val = from[prop]; |
|
224 if (!isUndefined(val)) { |
|
225 to[prop] = val; |
|
226 } |
|
227 } |
|
228 } |
|
229 |
|
230 return to; |
|
231 } |
|
232 |
|
233 var updateInProgress = false; |
|
234 |
|
235 // Moment prototype object |
|
236 function Moment(config) { |
|
237 copyConfig(this, config); |
|
238 this._d = new Date(config._d != null ? config._d.getTime() : NaN); |
|
239 if (!this.isValid()) { |
|
240 this._d = new Date(NaN); |
|
241 } |
|
242 // Prevent infinite loop in case updateOffset creates new moment |
|
243 // objects. |
|
244 if (updateInProgress === false) { |
|
245 updateInProgress = true; |
|
246 hooks.updateOffset(this); |
|
247 updateInProgress = false; |
|
248 } |
|
249 } |
|
250 |
|
251 function isMoment (obj) { |
|
252 return obj instanceof Moment || (obj != null && obj._isAMomentObject != null); |
|
253 } |
|
254 |
|
255 function absFloor (number) { |
|
256 if (number < 0) { |
|
257 // -0 -> 0 |
|
258 return Math.ceil(number) || 0; |
|
259 } else { |
|
260 return Math.floor(number); |
|
261 } |
|
262 } |
|
263 |
|
264 function toInt(argumentForCoercion) { |
|
265 var coercedNumber = +argumentForCoercion, |
|
266 value = 0; |
|
267 |
|
268 if (coercedNumber !== 0 && isFinite(coercedNumber)) { |
|
269 value = absFloor(coercedNumber); |
|
270 } |
|
271 |
|
272 return value; |
|
273 } |
|
274 |
|
275 // compare two arrays, return the number of differences |
|
276 function compareArrays(array1, array2, dontConvert) { |
|
277 var len = Math.min(array1.length, array2.length), |
|
278 lengthDiff = Math.abs(array1.length - array2.length), |
|
279 diffs = 0, |
|
280 i; |
|
281 for (i = 0; i < len; i++) { |
|
282 if ((dontConvert && array1[i] !== array2[i]) || |
|
283 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { |
|
284 diffs++; |
|
285 } |
|
286 } |
|
287 return diffs + lengthDiff; |
|
288 } |
|
289 |
|
290 function warn(msg) { |
|
291 if (hooks.suppressDeprecationWarnings === false && |
|
292 (typeof console !== 'undefined') && console.warn) { |
|
293 console.warn('Deprecation warning: ' + msg); |
|
294 } |
|
295 } |
|
296 |
|
297 function deprecate(msg, fn) { |
|
298 var firstTime = true; |
|
299 |
|
300 return extend(function () { |
|
301 if (hooks.deprecationHandler != null) { |
|
302 hooks.deprecationHandler(null, msg); |
|
303 } |
|
304 if (firstTime) { |
|
305 var args = []; |
|
306 var arg; |
|
307 for (var i = 0; i < arguments.length; i++) { |
|
308 arg = ''; |
|
309 if (typeof arguments[i] === 'object') { |
|
310 arg += '\n[' + i + '] '; |
|
311 for (var key in arguments[0]) { |
|
312 arg += key + ': ' + arguments[0][key] + ', '; |
|
313 } |
|
314 arg = arg.slice(0, -2); // Remove trailing comma and space |
|
315 } else { |
|
316 arg = arguments[i]; |
|
317 } |
|
318 args.push(arg); |
|
319 } |
|
320 warn(msg + '\nArguments: ' + Array.prototype.slice.call(args).join('') + '\n' + (new Error()).stack); |
|
321 firstTime = false; |
|
322 } |
|
323 return fn.apply(this, arguments); |
|
324 }, fn); |
|
325 } |
|
326 |
|
327 var deprecations = {}; |
|
328 |
|
329 function deprecateSimple(name, msg) { |
|
330 if (hooks.deprecationHandler != null) { |
|
331 hooks.deprecationHandler(name, msg); |
|
332 } |
|
333 if (!deprecations[name]) { |
|
334 warn(msg); |
|
335 deprecations[name] = true; |
|
336 } |
|
337 } |
|
338 |
|
339 hooks.suppressDeprecationWarnings = false; |
|
340 hooks.deprecationHandler = null; |
|
341 |
|
342 function isFunction(input) { |
|
343 return input instanceof Function || Object.prototype.toString.call(input) === '[object Function]'; |
|
344 } |
|
345 |
|
346 function set (config) { |
|
347 var prop, i; |
|
348 for (i in config) { |
|
349 prop = config[i]; |
|
350 if (isFunction(prop)) { |
|
351 this[i] = prop; |
|
352 } else { |
|
353 this['_' + i] = prop; |
|
354 } |
|
355 } |
|
356 this._config = config; |
|
357 // Lenient ordinal parsing accepts just a number in addition to |
|
358 // number + (possibly) stuff coming from _dayOfMonthOrdinalParse. |
|
359 // TODO: Remove "ordinalParse" fallback in next major release. |
|
360 this._dayOfMonthOrdinalParseLenient = new RegExp( |
|
361 (this._dayOfMonthOrdinalParse.source || this._ordinalParse.source) + |
|
362 '|' + (/\d{1,2}/).source); |
|
363 } |
|
364 |
|
365 function mergeConfigs(parentConfig, childConfig) { |
|
366 var res = extend({}, parentConfig), prop; |
|
367 for (prop in childConfig) { |
|
368 if (hasOwnProp(childConfig, prop)) { |
|
369 if (isObject(parentConfig[prop]) && isObject(childConfig[prop])) { |
|
370 res[prop] = {}; |
|
371 extend(res[prop], parentConfig[prop]); |
|
372 extend(res[prop], childConfig[prop]); |
|
373 } else if (childConfig[prop] != null) { |
|
374 res[prop] = childConfig[prop]; |
|
375 } else { |
|
376 delete res[prop]; |
|
377 } |
|
378 } |
|
379 } |
|
380 for (prop in parentConfig) { |
|
381 if (hasOwnProp(parentConfig, prop) && |
|
382 !hasOwnProp(childConfig, prop) && |
|
383 isObject(parentConfig[prop])) { |
|
384 // make sure changes to properties don't modify parent config |
|
385 res[prop] = extend({}, res[prop]); |
|
386 } |
|
387 } |
|
388 return res; |
|
389 } |
|
390 |
|
391 function Locale(config) { |
|
392 if (config != null) { |
|
393 this.set(config); |
|
394 } |
|
395 } |
|
396 |
|
397 var keys; |
|
398 |
|
399 if (Object.keys) { |
|
400 keys = Object.keys; |
|
401 } else { |
|
402 keys = function (obj) { |
|
403 var i, res = []; |
|
404 for (i in obj) { |
|
405 if (hasOwnProp(obj, i)) { |
|
406 res.push(i); |
|
407 } |
|
408 } |
|
409 return res; |
|
410 }; |
|
411 } |
|
412 |
|
413 var defaultCalendar = { |
|
414 sameDay : '[Today at] LT', |
|
415 nextDay : '[Tomorrow at] LT', |
|
416 nextWeek : 'dddd [at] LT', |
|
417 lastDay : '[Yesterday at] LT', |
|
418 lastWeek : '[Last] dddd [at] LT', |
|
419 sameElse : 'L' |
|
420 }; |
|
421 |
|
422 function calendar (key, mom, now) { |
|
423 var output = this._calendar[key] || this._calendar['sameElse']; |
|
424 return isFunction(output) ? output.call(mom, now) : output; |
|
425 } |
|
426 |
|
427 var defaultLongDateFormat = { |
|
428 LTS : 'h:mm:ss A', |
|
429 LT : 'h:mm A', |
|
430 L : 'MM/DD/YYYY', |
|
431 LL : 'MMMM D, YYYY', |
|
432 LLL : 'MMMM D, YYYY h:mm A', |
|
433 LLLL : 'dddd, MMMM D, YYYY h:mm A' |
|
434 }; |
|
435 |
|
436 function longDateFormat (key) { |
|
437 var format = this._longDateFormat[key], |
|
438 formatUpper = this._longDateFormat[key.toUpperCase()]; |
|
439 |
|
440 if (format || !formatUpper) { |
|
441 return format; |
|
442 } |
|
443 |
|
444 this._longDateFormat[key] = formatUpper.replace(/MMMM|MM|DD|dddd/g, function (val) { |
|
445 return val.slice(1); |
|
446 }); |
|
447 |
|
448 return this._longDateFormat[key]; |
|
449 } |
|
450 |
|
451 var defaultInvalidDate = 'Invalid date'; |
|
452 |
|
453 function invalidDate () { |
|
454 return this._invalidDate; |
|
455 } |
|
456 |
|
457 var defaultOrdinal = '%d'; |
|
458 var defaultDayOfMonthOrdinalParse = /\d{1,2}/; |
|
459 |
|
460 function ordinal (number) { |
|
461 return this._ordinal.replace('%d', number); |
|
462 } |
|
463 |
|
464 var defaultRelativeTime = { |
|
465 future : 'in %s', |
|
466 past : '%s ago', |
|
467 s : 'a few seconds', |
|
468 ss : '%d seconds', |
|
469 m : 'a minute', |
|
470 mm : '%d minutes', |
|
471 h : 'an hour', |
|
472 hh : '%d hours', |
|
473 d : 'a day', |
|
474 dd : '%d days', |
|
475 M : 'a month', |
|
476 MM : '%d months', |
|
477 y : 'a year', |
|
478 yy : '%d years' |
|
479 }; |
|
480 |
|
481 function relativeTime (number, withoutSuffix, string, isFuture) { |
|
482 var output = this._relativeTime[string]; |
|
483 return (isFunction(output)) ? |
|
484 output(number, withoutSuffix, string, isFuture) : |
|
485 output.replace(/%d/i, number); |
|
486 } |
|
487 |
|
488 function pastFuture (diff, output) { |
|
489 var format = this._relativeTime[diff > 0 ? 'future' : 'past']; |
|
490 return isFunction(format) ? format(output) : format.replace(/%s/i, output); |
|
491 } |
|
492 |
|
493 var aliases = {}; |
|
494 |
|
495 function addUnitAlias (unit, shorthand) { |
|
496 var lowerCase = unit.toLowerCase(); |
|
497 aliases[lowerCase] = aliases[lowerCase + 's'] = aliases[shorthand] = unit; |
|
498 } |
|
499 |
|
500 function normalizeUnits(units) { |
|
501 return typeof units === 'string' ? aliases[units] || aliases[units.toLowerCase()] : undefined; |
|
502 } |
|
503 |
|
504 function normalizeObjectUnits(inputObject) { |
|
505 var normalizedInput = {}, |
|
506 normalizedProp, |
|
507 prop; |
|
508 |
|
509 for (prop in inputObject) { |
|
510 if (hasOwnProp(inputObject, prop)) { |
|
511 normalizedProp = normalizeUnits(prop); |
|
512 if (normalizedProp) { |
|
513 normalizedInput[normalizedProp] = inputObject[prop]; |
|
514 } |
|
515 } |
|
516 } |
|
517 |
|
518 return normalizedInput; |
|
519 } |
|
520 |
|
521 var priorities = {}; |
|
522 |
|
523 function addUnitPriority(unit, priority) { |
|
524 priorities[unit] = priority; |
|
525 } |
|
526 |
|
527 function getPrioritizedUnits(unitsObj) { |
|
528 var units = []; |
|
529 for (var u in unitsObj) { |
|
530 units.push({unit: u, priority: priorities[u]}); |
|
531 } |
|
532 units.sort(function (a, b) { |
|
533 return a.priority - b.priority; |
|
534 }); |
|
535 return units; |
|
536 } |
|
537 |
|
538 function zeroFill(number, targetLength, forceSign) { |
|
539 var absNumber = '' + Math.abs(number), |
|
540 zerosToFill = targetLength - absNumber.length, |
|
541 sign = number >= 0; |
|
542 return (sign ? (forceSign ? '+' : '') : '-') + |
|
543 Math.pow(10, Math.max(0, zerosToFill)).toString().substr(1) + absNumber; |
|
544 } |
|
545 |
|
546 var formattingTokens = /(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g; |
|
547 |
|
548 var localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g; |
|
549 |
|
550 var formatFunctions = {}; |
|
551 |
|
552 var formatTokenFunctions = {}; |
|
553 |
|
554 // token: 'M' |
|
555 // padded: ['MM', 2] |
|
556 // ordinal: 'Mo' |
|
557 // callback: function () { this.month() + 1 } |
|
558 function addFormatToken (token, padded, ordinal, callback) { |
|
559 var func = callback; |
|
560 if (typeof callback === 'string') { |
|
561 func = function () { |
|
562 return this[callback](); |
|
563 }; |
|
564 } |
|
565 if (token) { |
|
566 formatTokenFunctions[token] = func; |
|
567 } |
|
568 if (padded) { |
|
569 formatTokenFunctions[padded[0]] = function () { |
|
570 return zeroFill(func.apply(this, arguments), padded[1], padded[2]); |
|
571 }; |
|
572 } |
|
573 if (ordinal) { |
|
574 formatTokenFunctions[ordinal] = function () { |
|
575 return this.localeData().ordinal(func.apply(this, arguments), token); |
|
576 }; |
|
577 } |
|
578 } |
|
579 |
|
580 function removeFormattingTokens(input) { |
|
581 if (input.match(/\[[\s\S]/)) { |
|
582 return input.replace(/^\[|\]$/g, ''); |
|
583 } |
|
584 return input.replace(/\\/g, ''); |
|
585 } |
|
586 |
|
587 function makeFormatFunction(format) { |
|
588 var array = format.match(formattingTokens), i, length; |
|
589 |
|
590 for (i = 0, length = array.length; i < length; i++) { |
|
591 if (formatTokenFunctions[array[i]]) { |
|
592 array[i] = formatTokenFunctions[array[i]]; |
|
593 } else { |
|
594 array[i] = removeFormattingTokens(array[i]); |
|
595 } |
|
596 } |
|
597 |
|
598 return function (mom) { |
|
599 var output = '', i; |
|
600 for (i = 0; i < length; i++) { |
|
601 output += isFunction(array[i]) ? array[i].call(mom, format) : array[i]; |
|
602 } |
|
603 return output; |
|
604 }; |
|
605 } |
|
606 |
|
607 // format date using native date object |
|
608 function formatMoment(m, format) { |
|
609 if (!m.isValid()) { |
|
610 return m.localeData().invalidDate(); |
|
611 } |
|
612 |
|
613 format = expandFormat(format, m.localeData()); |
|
614 formatFunctions[format] = formatFunctions[format] || makeFormatFunction(format); |
|
615 |
|
616 return formatFunctions[format](m); |
|
617 } |
|
618 |
|
619 function expandFormat(format, locale) { |
|
620 var i = 5; |
|
621 |
|
622 function replaceLongDateFormatTokens(input) { |
|
623 return locale.longDateFormat(input) || input; |
|
624 } |
|
625 |
|
626 localFormattingTokens.lastIndex = 0; |
|
627 while (i >= 0 && localFormattingTokens.test(format)) { |
|
628 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); |
|
629 localFormattingTokens.lastIndex = 0; |
|
630 i -= 1; |
|
631 } |
|
632 |
|
633 return format; |
|
634 } |
|
635 |
|
636 var match1 = /\d/; // 0 - 9 |
|
637 var match2 = /\d\d/; // 00 - 99 |
|
638 var match3 = /\d{3}/; // 000 - 999 |
|
639 var match4 = /\d{4}/; // 0000 - 9999 |
|
640 var match6 = /[+-]?\d{6}/; // -999999 - 999999 |
|
641 var match1to2 = /\d\d?/; // 0 - 99 |
|
642 var match3to4 = /\d\d\d\d?/; // 999 - 9999 |
|
643 var match5to6 = /\d\d\d\d\d\d?/; // 99999 - 999999 |
|
644 var match1to3 = /\d{1,3}/; // 0 - 999 |
|
645 var match1to4 = /\d{1,4}/; // 0 - 9999 |
|
646 var match1to6 = /[+-]?\d{1,6}/; // -999999 - 999999 |
|
647 |
|
648 var matchUnsigned = /\d+/; // 0 - inf |
|
649 var matchSigned = /[+-]?\d+/; // -inf - inf |
|
650 |
|
651 var matchOffset = /Z|[+-]\d\d:?\d\d/gi; // +00:00 -00:00 +0000 -0000 or Z |
|
652 var matchShortOffset = /Z|[+-]\d\d(?::?\d\d)?/gi; // +00 -00 +00:00 -00:00 +0000 -0000 or Z |
|
653 |
|
654 var matchTimestamp = /[+-]?\d+(\.\d{1,3})?/; // 123456789 123456789.123 |
|
655 |
|
656 // any word (or two) characters or numbers including two/three word month in arabic. |
|
657 // includes scottish gaelic two word and hyphenated months |
|
658 var matchWord = /[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i; |
|
659 |
|
660 var regexes = {}; |
|
661 |
|
662 function addRegexToken (token, regex, strictRegex) { |
|
663 regexes[token] = isFunction(regex) ? regex : function (isStrict, localeData) { |
|
664 return (isStrict && strictRegex) ? strictRegex : regex; |
|
665 }; |
|
666 } |
|
667 |
|
668 function getParseRegexForToken (token, config) { |
|
669 if (!hasOwnProp(regexes, token)) { |
|
670 return new RegExp(unescapeFormat(token)); |
|
671 } |
|
672 |
|
673 return regexes[token](config._strict, config._locale); |
|
674 } |
|
675 |
|
676 // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript |
|
677 function unescapeFormat(s) { |
|
678 return regexEscape(s.replace('\\', '').replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { |
|
679 return p1 || p2 || p3 || p4; |
|
680 })); |
|
681 } |
|
682 |
|
683 function regexEscape(s) { |
|
684 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); |
|
685 } |
|
686 |
|
687 var tokens = {}; |
|
688 |
|
689 function addParseToken (token, callback) { |
|
690 var i, func = callback; |
|
691 if (typeof token === 'string') { |
|
692 token = [token]; |
|
693 } |
|
694 if (isNumber(callback)) { |
|
695 func = function (input, array) { |
|
696 array[callback] = toInt(input); |
|
697 }; |
|
698 } |
|
699 for (i = 0; i < token.length; i++) { |
|
700 tokens[token[i]] = func; |
|
701 } |
|
702 } |
|
703 |
|
704 function addWeekParseToken (token, callback) { |
|
705 addParseToken(token, function (input, array, config, token) { |
|
706 config._w = config._w || {}; |
|
707 callback(input, config._w, config, token); |
|
708 }); |
|
709 } |
|
710 |
|
711 function addTimeToArrayFromToken(token, input, config) { |
|
712 if (input != null && hasOwnProp(tokens, token)) { |
|
713 tokens[token](input, config._a, config, token); |
|
714 } |
|
715 } |
|
716 |
|
717 var YEAR = 0; |
|
718 var MONTH = 1; |
|
719 var DATE = 2; |
|
720 var HOUR = 3; |
|
721 var MINUTE = 4; |
|
722 var SECOND = 5; |
|
723 var MILLISECOND = 6; |
|
724 var WEEK = 7; |
|
725 var WEEKDAY = 8; |
|
726 |
|
727 // FORMATTING |
|
728 |
|
729 addFormatToken('Y', 0, 0, function () { |
|
730 var y = this.year(); |
|
731 return y <= 9999 ? '' + y : '+' + y; |
|
732 }); |
|
733 |
|
734 addFormatToken(0, ['YY', 2], 0, function () { |
|
735 return this.year() % 100; |
|
736 }); |
|
737 |
|
738 addFormatToken(0, ['YYYY', 4], 0, 'year'); |
|
739 addFormatToken(0, ['YYYYY', 5], 0, 'year'); |
|
740 addFormatToken(0, ['YYYYYY', 6, true], 0, 'year'); |
|
741 |
|
742 // ALIASES |
|
743 |
|
744 addUnitAlias('year', 'y'); |
|
745 |
|
746 // PRIORITIES |
|
747 |
|
748 addUnitPriority('year', 1); |
|
749 |
|
750 // PARSING |
|
751 |
|
752 addRegexToken('Y', matchSigned); |
|
753 addRegexToken('YY', match1to2, match2); |
|
754 addRegexToken('YYYY', match1to4, match4); |
|
755 addRegexToken('YYYYY', match1to6, match6); |
|
756 addRegexToken('YYYYYY', match1to6, match6); |
|
757 |
|
758 addParseToken(['YYYYY', 'YYYYYY'], YEAR); |
|
759 addParseToken('YYYY', function (input, array) { |
|
760 array[YEAR] = input.length === 2 ? hooks.parseTwoDigitYear(input) : toInt(input); |
|
761 }); |
|
762 addParseToken('YY', function (input, array) { |
|
763 array[YEAR] = hooks.parseTwoDigitYear(input); |
|
764 }); |
|
765 addParseToken('Y', function (input, array) { |
|
766 array[YEAR] = parseInt(input, 10); |
|
767 }); |
|
768 |
|
769 // HELPERS |
|
770 |
|
771 function daysInYear(year) { |
|
772 return isLeapYear(year) ? 366 : 365; |
|
773 } |
|
774 |
|
775 function isLeapYear(year) { |
|
776 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; |
|
777 } |
|
778 |
|
779 // HOOKS |
|
780 |
|
781 hooks.parseTwoDigitYear = function (input) { |
|
782 return toInt(input) + (toInt(input) > 68 ? 1900 : 2000); |
|
783 }; |
|
784 |
|
785 // MOMENTS |
|
786 |
|
787 var getSetYear = makeGetSet('FullYear', true); |
|
788 |
|
789 function getIsLeapYear () { |
|
790 return isLeapYear(this.year()); |
|
791 } |
|
792 |
|
793 function makeGetSet (unit, keepTime) { |
|
794 return function (value) { |
|
795 if (value != null) { |
|
796 set$1(this, unit, value); |
|
797 hooks.updateOffset(this, keepTime); |
|
798 return this; |
|
799 } else { |
|
800 return get(this, unit); |
|
801 } |
|
802 }; |
|
803 } |
|
804 |
|
805 function get (mom, unit) { |
|
806 return mom.isValid() ? |
|
807 mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]() : NaN; |
|
808 } |
|
809 |
|
810 function set$1 (mom, unit, value) { |
|
811 if (mom.isValid() && !isNaN(value)) { |
|
812 if (unit === 'FullYear' && isLeapYear(mom.year()) && mom.month() === 1 && mom.date() === 29) { |
|
813 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value, mom.month(), daysInMonth(value, mom.month())); |
|
814 } |
|
815 else { |
|
816 mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value); |
|
817 } |
|
818 } |
|
819 } |
|
820 |
|
821 // MOMENTS |
|
822 |
|
823 function stringGet (units) { |
|
824 units = normalizeUnits(units); |
|
825 if (isFunction(this[units])) { |
|
826 return this[units](); |
|
827 } |
|
828 return this; |
|
829 } |
|
830 |
|
831 |
|
832 function stringSet (units, value) { |
|
833 if (typeof units === 'object') { |
|
834 units = normalizeObjectUnits(units); |
|
835 var prioritized = getPrioritizedUnits(units); |
|
836 for (var i = 0; i < prioritized.length; i++) { |
|
837 this[prioritized[i].unit](units[prioritized[i].unit]); |
|
838 } |
|
839 } else { |
|
840 units = normalizeUnits(units); |
|
841 if (isFunction(this[units])) { |
|
842 return this[units](value); |
|
843 } |
|
844 } |
|
845 return this; |
|
846 } |
|
847 |
|
848 function mod(n, x) { |
|
849 return ((n % x) + x) % x; |
|
850 } |
|
851 |
|
852 var indexOf; |
|
853 |
|
854 if (Array.prototype.indexOf) { |
|
855 indexOf = Array.prototype.indexOf; |
|
856 } else { |
|
857 indexOf = function (o) { |
|
858 // I know |
|
859 var i; |
|
860 for (i = 0; i < this.length; ++i) { |
|
861 if (this[i] === o) { |
|
862 return i; |
|
863 } |
|
864 } |
|
865 return -1; |
|
866 }; |
|
867 } |
|
868 |
|
869 function daysInMonth(year, month) { |
|
870 if (isNaN(year) || isNaN(month)) { |
|
871 return NaN; |
|
872 } |
|
873 var modMonth = mod(month, 12); |
|
874 year += (month - modMonth) / 12; |
|
875 return modMonth === 1 ? (isLeapYear(year) ? 29 : 28) : (31 - modMonth % 7 % 2); |
|
876 } |
|
877 |
|
878 // FORMATTING |
|
879 |
|
880 addFormatToken('M', ['MM', 2], 'Mo', function () { |
|
881 return this.month() + 1; |
|
882 }); |
|
883 |
|
884 addFormatToken('MMM', 0, 0, function (format) { |
|
885 return this.localeData().monthsShort(this, format); |
|
886 }); |
|
887 |
|
888 addFormatToken('MMMM', 0, 0, function (format) { |
|
889 return this.localeData().months(this, format); |
|
890 }); |
|
891 |
|
892 // ALIASES |
|
893 |
|
894 addUnitAlias('month', 'M'); |
|
895 |
|
896 // PRIORITY |
|
897 |
|
898 addUnitPriority('month', 8); |
|
899 |
|
900 // PARSING |
|
901 |
|
902 addRegexToken('M', match1to2); |
|
903 addRegexToken('MM', match1to2, match2); |
|
904 addRegexToken('MMM', function (isStrict, locale) { |
|
905 return locale.monthsShortRegex(isStrict); |
|
906 }); |
|
907 addRegexToken('MMMM', function (isStrict, locale) { |
|
908 return locale.monthsRegex(isStrict); |
|
909 }); |
|
910 |
|
911 addParseToken(['M', 'MM'], function (input, array) { |
|
912 array[MONTH] = toInt(input) - 1; |
|
913 }); |
|
914 |
|
915 addParseToken(['MMM', 'MMMM'], function (input, array, config, token) { |
|
916 var month = config._locale.monthsParse(input, token, config._strict); |
|
917 // if we didn't find a month name, mark the date as invalid. |
|
918 if (month != null) { |
|
919 array[MONTH] = month; |
|
920 } else { |
|
921 getParsingFlags(config).invalidMonth = input; |
|
922 } |
|
923 }); |
|
924 |
|
925 // LOCALES |
|
926 |
|
927 var MONTHS_IN_FORMAT = /D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/; |
|
928 var defaultLocaleMonths = 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'); |
|
929 function localeMonths (m, format) { |
|
930 if (!m) { |
|
931 return isArray(this._months) ? this._months : |
|
932 this._months['standalone']; |
|
933 } |
|
934 return isArray(this._months) ? this._months[m.month()] : |
|
935 this._months[(this._months.isFormat || MONTHS_IN_FORMAT).test(format) ? 'format' : 'standalone'][m.month()]; |
|
936 } |
|
937 |
|
938 var defaultLocaleMonthsShort = 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'); |
|
939 function localeMonthsShort (m, format) { |
|
940 if (!m) { |
|
941 return isArray(this._monthsShort) ? this._monthsShort : |
|
942 this._monthsShort['standalone']; |
|
943 } |
|
944 return isArray(this._monthsShort) ? this._monthsShort[m.month()] : |
|
945 this._monthsShort[MONTHS_IN_FORMAT.test(format) ? 'format' : 'standalone'][m.month()]; |
|
946 } |
|
947 |
|
948 function handleStrictParse(monthName, format, strict) { |
|
949 var i, ii, mom, llc = monthName.toLocaleLowerCase(); |
|
950 if (!this._monthsParse) { |
|
951 // this is not used |
|
952 this._monthsParse = []; |
|
953 this._longMonthsParse = []; |
|
954 this._shortMonthsParse = []; |
|
955 for (i = 0; i < 12; ++i) { |
|
956 mom = createUTC([2000, i]); |
|
957 this._shortMonthsParse[i] = this.monthsShort(mom, '').toLocaleLowerCase(); |
|
958 this._longMonthsParse[i] = this.months(mom, '').toLocaleLowerCase(); |
|
959 } |
|
960 } |
|
961 |
|
962 if (strict) { |
|
963 if (format === 'MMM') { |
|
964 ii = indexOf.call(this._shortMonthsParse, llc); |
|
965 return ii !== -1 ? ii : null; |
|
966 } else { |
|
967 ii = indexOf.call(this._longMonthsParse, llc); |
|
968 return ii !== -1 ? ii : null; |
|
969 } |
|
970 } else { |
|
971 if (format === 'MMM') { |
|
972 ii = indexOf.call(this._shortMonthsParse, llc); |
|
973 if (ii !== -1) { |
|
974 return ii; |
|
975 } |
|
976 ii = indexOf.call(this._longMonthsParse, llc); |
|
977 return ii !== -1 ? ii : null; |
|
978 } else { |
|
979 ii = indexOf.call(this._longMonthsParse, llc); |
|
980 if (ii !== -1) { |
|
981 return ii; |
|
982 } |
|
983 ii = indexOf.call(this._shortMonthsParse, llc); |
|
984 return ii !== -1 ? ii : null; |
|
985 } |
|
986 } |
|
987 } |
|
988 |
|
989 function localeMonthsParse (monthName, format, strict) { |
|
990 var i, mom, regex; |
|
991 |
|
992 if (this._monthsParseExact) { |
|
993 return handleStrictParse.call(this, monthName, format, strict); |
|
994 } |
|
995 |
|
996 if (!this._monthsParse) { |
|
997 this._monthsParse = []; |
|
998 this._longMonthsParse = []; |
|
999 this._shortMonthsParse = []; |
|
1000 } |
|
1001 |
|
1002 // TODO: add sorting |
|
1003 // Sorting makes sure if one month (or abbr) is a prefix of another |
|
1004 // see sorting in computeMonthsParse |
|
1005 for (i = 0; i < 12; i++) { |
|
1006 // make the regex if we don't have it already |
|
1007 mom = createUTC([2000, i]); |
|
1008 if (strict && !this._longMonthsParse[i]) { |
|
1009 this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i'); |
|
1010 this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i'); |
|
1011 } |
|
1012 if (!strict && !this._monthsParse[i]) { |
|
1013 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); |
|
1014 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); |
|
1015 } |
|
1016 // test the regex |
|
1017 if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) { |
|
1018 return i; |
|
1019 } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) { |
|
1020 return i; |
|
1021 } else if (!strict && this._monthsParse[i].test(monthName)) { |
|
1022 return i; |
|
1023 } |
|
1024 } |
|
1025 } |
|
1026 |
|
1027 // MOMENTS |
|
1028 |
|
1029 function setMonth (mom, value) { |
|
1030 var dayOfMonth; |
|
1031 |
|
1032 if (!mom.isValid()) { |
|
1033 // No op |
|
1034 return mom; |
|
1035 } |
|
1036 |
|
1037 if (typeof value === 'string') { |
|
1038 if (/^\d+$/.test(value)) { |
|
1039 value = toInt(value); |
|
1040 } else { |
|
1041 value = mom.localeData().monthsParse(value); |
|
1042 // TODO: Another silent failure? |
|
1043 if (!isNumber(value)) { |
|
1044 return mom; |
|
1045 } |
|
1046 } |
|
1047 } |
|
1048 |
|
1049 dayOfMonth = Math.min(mom.date(), daysInMonth(mom.year(), value)); |
|
1050 mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth); |
|
1051 return mom; |
|
1052 } |
|
1053 |
|
1054 function getSetMonth (value) { |
|
1055 if (value != null) { |
|
1056 setMonth(this, value); |
|
1057 hooks.updateOffset(this, true); |
|
1058 return this; |
|
1059 } else { |
|
1060 return get(this, 'Month'); |
|
1061 } |
|
1062 } |
|
1063 |
|
1064 function getDaysInMonth () { |
|
1065 return daysInMonth(this.year(), this.month()); |
|
1066 } |
|
1067 |
|
1068 var defaultMonthsShortRegex = matchWord; |
|
1069 function monthsShortRegex (isStrict) { |
|
1070 if (this._monthsParseExact) { |
|
1071 if (!hasOwnProp(this, '_monthsRegex')) { |
|
1072 computeMonthsParse.call(this); |
|
1073 } |
|
1074 if (isStrict) { |
|
1075 return this._monthsShortStrictRegex; |
|
1076 } else { |
|
1077 return this._monthsShortRegex; |
|
1078 } |
|
1079 } else { |
|
1080 if (!hasOwnProp(this, '_monthsShortRegex')) { |
|
1081 this._monthsShortRegex = defaultMonthsShortRegex; |
|
1082 } |
|
1083 return this._monthsShortStrictRegex && isStrict ? |
|
1084 this._monthsShortStrictRegex : this._monthsShortRegex; |
|
1085 } |
|
1086 } |
|
1087 |
|
1088 var defaultMonthsRegex = matchWord; |
|
1089 function monthsRegex (isStrict) { |
|
1090 if (this._monthsParseExact) { |
|
1091 if (!hasOwnProp(this, '_monthsRegex')) { |
|
1092 computeMonthsParse.call(this); |
|
1093 } |
|
1094 if (isStrict) { |
|
1095 return this._monthsStrictRegex; |
|
1096 } else { |
|
1097 return this._monthsRegex; |
|
1098 } |
|
1099 } else { |
|
1100 if (!hasOwnProp(this, '_monthsRegex')) { |
|
1101 this._monthsRegex = defaultMonthsRegex; |
|
1102 } |
|
1103 return this._monthsStrictRegex && isStrict ? |
|
1104 this._monthsStrictRegex : this._monthsRegex; |
|
1105 } |
|
1106 } |
|
1107 |
|
1108 function computeMonthsParse () { |
|
1109 function cmpLenRev(a, b) { |
|
1110 return b.length - a.length; |
|
1111 } |
|
1112 |
|
1113 var shortPieces = [], longPieces = [], mixedPieces = [], |
|
1114 i, mom; |
|
1115 for (i = 0; i < 12; i++) { |
|
1116 // make the regex if we don't have it already |
|
1117 mom = createUTC([2000, i]); |
|
1118 shortPieces.push(this.monthsShort(mom, '')); |
|
1119 longPieces.push(this.months(mom, '')); |
|
1120 mixedPieces.push(this.months(mom, '')); |
|
1121 mixedPieces.push(this.monthsShort(mom, '')); |
|
1122 } |
|
1123 // Sorting makes sure if one month (or abbr) is a prefix of another it |
|
1124 // will match the longer piece. |
|
1125 shortPieces.sort(cmpLenRev); |
|
1126 longPieces.sort(cmpLenRev); |
|
1127 mixedPieces.sort(cmpLenRev); |
|
1128 for (i = 0; i < 12; i++) { |
|
1129 shortPieces[i] = regexEscape(shortPieces[i]); |
|
1130 longPieces[i] = regexEscape(longPieces[i]); |
|
1131 } |
|
1132 for (i = 0; i < 24; i++) { |
|
1133 mixedPieces[i] = regexEscape(mixedPieces[i]); |
|
1134 } |
|
1135 |
|
1136 this._monthsRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); |
|
1137 this._monthsShortRegex = this._monthsRegex; |
|
1138 this._monthsStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); |
|
1139 this._monthsShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); |
|
1140 } |
|
1141 |
|
1142 function createDate (y, m, d, h, M, s, ms) { |
|
1143 // can't just apply() to create a date: |
|
1144 // https://stackoverflow.com/q/181348 |
|
1145 var date = new Date(y, m, d, h, M, s, ms); |
|
1146 |
|
1147 // the date constructor remaps years 0-99 to 1900-1999 |
|
1148 if (y < 100 && y >= 0 && isFinite(date.getFullYear())) { |
|
1149 date.setFullYear(y); |
|
1150 } |
|
1151 return date; |
|
1152 } |
|
1153 |
|
1154 function createUTCDate (y) { |
|
1155 var date = new Date(Date.UTC.apply(null, arguments)); |
|
1156 |
|
1157 // the Date.UTC function remaps years 0-99 to 1900-1999 |
|
1158 if (y < 100 && y >= 0 && isFinite(date.getUTCFullYear())) { |
|
1159 date.setUTCFullYear(y); |
|
1160 } |
|
1161 return date; |
|
1162 } |
|
1163 |
|
1164 // start-of-first-week - start-of-year |
|
1165 function firstWeekOffset(year, dow, doy) { |
|
1166 var // first-week day -- which january is always in the first week (4 for iso, 1 for other) |
|
1167 fwd = 7 + dow - doy, |
|
1168 // first-week day local weekday -- which local weekday is fwd |
|
1169 fwdlw = (7 + createUTCDate(year, 0, fwd).getUTCDay() - dow) % 7; |
|
1170 |
|
1171 return -fwdlw + fwd - 1; |
|
1172 } |
|
1173 |
|
1174 // https://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday |
|
1175 function dayOfYearFromWeeks(year, week, weekday, dow, doy) { |
|
1176 var localWeekday = (7 + weekday - dow) % 7, |
|
1177 weekOffset = firstWeekOffset(year, dow, doy), |
|
1178 dayOfYear = 1 + 7 * (week - 1) + localWeekday + weekOffset, |
|
1179 resYear, resDayOfYear; |
|
1180 |
|
1181 if (dayOfYear <= 0) { |
|
1182 resYear = year - 1; |
|
1183 resDayOfYear = daysInYear(resYear) + dayOfYear; |
|
1184 } else if (dayOfYear > daysInYear(year)) { |
|
1185 resYear = year + 1; |
|
1186 resDayOfYear = dayOfYear - daysInYear(year); |
|
1187 } else { |
|
1188 resYear = year; |
|
1189 resDayOfYear = dayOfYear; |
|
1190 } |
|
1191 |
|
1192 return { |
|
1193 year: resYear, |
|
1194 dayOfYear: resDayOfYear |
|
1195 }; |
|
1196 } |
|
1197 |
|
1198 function weekOfYear(mom, dow, doy) { |
|
1199 var weekOffset = firstWeekOffset(mom.year(), dow, doy), |
|
1200 week = Math.floor((mom.dayOfYear() - weekOffset - 1) / 7) + 1, |
|
1201 resWeek, resYear; |
|
1202 |
|
1203 if (week < 1) { |
|
1204 resYear = mom.year() - 1; |
|
1205 resWeek = week + weeksInYear(resYear, dow, doy); |
|
1206 } else if (week > weeksInYear(mom.year(), dow, doy)) { |
|
1207 resWeek = week - weeksInYear(mom.year(), dow, doy); |
|
1208 resYear = mom.year() + 1; |
|
1209 } else { |
|
1210 resYear = mom.year(); |
|
1211 resWeek = week; |
|
1212 } |
|
1213 |
|
1214 return { |
|
1215 week: resWeek, |
|
1216 year: resYear |
|
1217 }; |
|
1218 } |
|
1219 |
|
1220 function weeksInYear(year, dow, doy) { |
|
1221 var weekOffset = firstWeekOffset(year, dow, doy), |
|
1222 weekOffsetNext = firstWeekOffset(year + 1, dow, doy); |
|
1223 return (daysInYear(year) - weekOffset + weekOffsetNext) / 7; |
|
1224 } |
|
1225 |
|
1226 // FORMATTING |
|
1227 |
|
1228 addFormatToken('w', ['ww', 2], 'wo', 'week'); |
|
1229 addFormatToken('W', ['WW', 2], 'Wo', 'isoWeek'); |
|
1230 |
|
1231 // ALIASES |
|
1232 |
|
1233 addUnitAlias('week', 'w'); |
|
1234 addUnitAlias('isoWeek', 'W'); |
|
1235 |
|
1236 // PRIORITIES |
|
1237 |
|
1238 addUnitPriority('week', 5); |
|
1239 addUnitPriority('isoWeek', 5); |
|
1240 |
|
1241 // PARSING |
|
1242 |
|
1243 addRegexToken('w', match1to2); |
|
1244 addRegexToken('ww', match1to2, match2); |
|
1245 addRegexToken('W', match1to2); |
|
1246 addRegexToken('WW', match1to2, match2); |
|
1247 |
|
1248 addWeekParseToken(['w', 'ww', 'W', 'WW'], function (input, week, config, token) { |
|
1249 week[token.substr(0, 1)] = toInt(input); |
|
1250 }); |
|
1251 |
|
1252 // HELPERS |
|
1253 |
|
1254 // LOCALES |
|
1255 |
|
1256 function localeWeek (mom) { |
|
1257 return weekOfYear(mom, this._week.dow, this._week.doy).week; |
|
1258 } |
|
1259 |
|
1260 var defaultLocaleWeek = { |
|
1261 dow : 0, // Sunday is the first day of the week. |
|
1262 doy : 6 // The week that contains Jan 1st is the first week of the year. |
|
1263 }; |
|
1264 |
|
1265 function localeFirstDayOfWeek () { |
|
1266 return this._week.dow; |
|
1267 } |
|
1268 |
|
1269 function localeFirstDayOfYear () { |
|
1270 return this._week.doy; |
|
1271 } |
|
1272 |
|
1273 // MOMENTS |
|
1274 |
|
1275 function getSetWeek (input) { |
|
1276 var week = this.localeData().week(this); |
|
1277 return input == null ? week : this.add((input - week) * 7, 'd'); |
|
1278 } |
|
1279 |
|
1280 function getSetISOWeek (input) { |
|
1281 var week = weekOfYear(this, 1, 4).week; |
|
1282 return input == null ? week : this.add((input - week) * 7, 'd'); |
|
1283 } |
|
1284 |
|
1285 // FORMATTING |
|
1286 |
|
1287 addFormatToken('d', 0, 'do', 'day'); |
|
1288 |
|
1289 addFormatToken('dd', 0, 0, function (format) { |
|
1290 return this.localeData().weekdaysMin(this, format); |
|
1291 }); |
|
1292 |
|
1293 addFormatToken('ddd', 0, 0, function (format) { |
|
1294 return this.localeData().weekdaysShort(this, format); |
|
1295 }); |
|
1296 |
|
1297 addFormatToken('dddd', 0, 0, function (format) { |
|
1298 return this.localeData().weekdays(this, format); |
|
1299 }); |
|
1300 |
|
1301 addFormatToken('e', 0, 0, 'weekday'); |
|
1302 addFormatToken('E', 0, 0, 'isoWeekday'); |
|
1303 |
|
1304 // ALIASES |
|
1305 |
|
1306 addUnitAlias('day', 'd'); |
|
1307 addUnitAlias('weekday', 'e'); |
|
1308 addUnitAlias('isoWeekday', 'E'); |
|
1309 |
|
1310 // PRIORITY |
|
1311 addUnitPriority('day', 11); |
|
1312 addUnitPriority('weekday', 11); |
|
1313 addUnitPriority('isoWeekday', 11); |
|
1314 |
|
1315 // PARSING |
|
1316 |
|
1317 addRegexToken('d', match1to2); |
|
1318 addRegexToken('e', match1to2); |
|
1319 addRegexToken('E', match1to2); |
|
1320 addRegexToken('dd', function (isStrict, locale) { |
|
1321 return locale.weekdaysMinRegex(isStrict); |
|
1322 }); |
|
1323 addRegexToken('ddd', function (isStrict, locale) { |
|
1324 return locale.weekdaysShortRegex(isStrict); |
|
1325 }); |
|
1326 addRegexToken('dddd', function (isStrict, locale) { |
|
1327 return locale.weekdaysRegex(isStrict); |
|
1328 }); |
|
1329 |
|
1330 addWeekParseToken(['dd', 'ddd', 'dddd'], function (input, week, config, token) { |
|
1331 var weekday = config._locale.weekdaysParse(input, token, config._strict); |
|
1332 // if we didn't get a weekday name, mark the date as invalid |
|
1333 if (weekday != null) { |
|
1334 week.d = weekday; |
|
1335 } else { |
|
1336 getParsingFlags(config).invalidWeekday = input; |
|
1337 } |
|
1338 }); |
|
1339 |
|
1340 addWeekParseToken(['d', 'e', 'E'], function (input, week, config, token) { |
|
1341 week[token] = toInt(input); |
|
1342 }); |
|
1343 |
|
1344 // HELPERS |
|
1345 |
|
1346 function parseWeekday(input, locale) { |
|
1347 if (typeof input !== 'string') { |
|
1348 return input; |
|
1349 } |
|
1350 |
|
1351 if (!isNaN(input)) { |
|
1352 return parseInt(input, 10); |
|
1353 } |
|
1354 |
|
1355 input = locale.weekdaysParse(input); |
|
1356 if (typeof input === 'number') { |
|
1357 return input; |
|
1358 } |
|
1359 |
|
1360 return null; |
|
1361 } |
|
1362 |
|
1363 function parseIsoWeekday(input, locale) { |
|
1364 if (typeof input === 'string') { |
|
1365 return locale.weekdaysParse(input) % 7 || 7; |
|
1366 } |
|
1367 return isNaN(input) ? null : input; |
|
1368 } |
|
1369 |
|
1370 // LOCALES |
|
1371 |
|
1372 var defaultLocaleWeekdays = 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'); |
|
1373 function localeWeekdays (m, format) { |
|
1374 if (!m) { |
|
1375 return isArray(this._weekdays) ? this._weekdays : |
|
1376 this._weekdays['standalone']; |
|
1377 } |
|
1378 return isArray(this._weekdays) ? this._weekdays[m.day()] : |
|
1379 this._weekdays[this._weekdays.isFormat.test(format) ? 'format' : 'standalone'][m.day()]; |
|
1380 } |
|
1381 |
|
1382 var defaultLocaleWeekdaysShort = 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'); |
|
1383 function localeWeekdaysShort (m) { |
|
1384 return (m) ? this._weekdaysShort[m.day()] : this._weekdaysShort; |
|
1385 } |
|
1386 |
|
1387 var defaultLocaleWeekdaysMin = 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'); |
|
1388 function localeWeekdaysMin (m) { |
|
1389 return (m) ? this._weekdaysMin[m.day()] : this._weekdaysMin; |
|
1390 } |
|
1391 |
|
1392 function handleStrictParse$1(weekdayName, format, strict) { |
|
1393 var i, ii, mom, llc = weekdayName.toLocaleLowerCase(); |
|
1394 if (!this._weekdaysParse) { |
|
1395 this._weekdaysParse = []; |
|
1396 this._shortWeekdaysParse = []; |
|
1397 this._minWeekdaysParse = []; |
|
1398 |
|
1399 for (i = 0; i < 7; ++i) { |
|
1400 mom = createUTC([2000, 1]).day(i); |
|
1401 this._minWeekdaysParse[i] = this.weekdaysMin(mom, '').toLocaleLowerCase(); |
|
1402 this._shortWeekdaysParse[i] = this.weekdaysShort(mom, '').toLocaleLowerCase(); |
|
1403 this._weekdaysParse[i] = this.weekdays(mom, '').toLocaleLowerCase(); |
|
1404 } |
|
1405 } |
|
1406 |
|
1407 if (strict) { |
|
1408 if (format === 'dddd') { |
|
1409 ii = indexOf.call(this._weekdaysParse, llc); |
|
1410 return ii !== -1 ? ii : null; |
|
1411 } else if (format === 'ddd') { |
|
1412 ii = indexOf.call(this._shortWeekdaysParse, llc); |
|
1413 return ii !== -1 ? ii : null; |
|
1414 } else { |
|
1415 ii = indexOf.call(this._minWeekdaysParse, llc); |
|
1416 return ii !== -1 ? ii : null; |
|
1417 } |
|
1418 } else { |
|
1419 if (format === 'dddd') { |
|
1420 ii = indexOf.call(this._weekdaysParse, llc); |
|
1421 if (ii !== -1) { |
|
1422 return ii; |
|
1423 } |
|
1424 ii = indexOf.call(this._shortWeekdaysParse, llc); |
|
1425 if (ii !== -1) { |
|
1426 return ii; |
|
1427 } |
|
1428 ii = indexOf.call(this._minWeekdaysParse, llc); |
|
1429 return ii !== -1 ? ii : null; |
|
1430 } else if (format === 'ddd') { |
|
1431 ii = indexOf.call(this._shortWeekdaysParse, llc); |
|
1432 if (ii !== -1) { |
|
1433 return ii; |
|
1434 } |
|
1435 ii = indexOf.call(this._weekdaysParse, llc); |
|
1436 if (ii !== -1) { |
|
1437 return ii; |
|
1438 } |
|
1439 ii = indexOf.call(this._minWeekdaysParse, llc); |
|
1440 return ii !== -1 ? ii : null; |
|
1441 } else { |
|
1442 ii = indexOf.call(this._minWeekdaysParse, llc); |
|
1443 if (ii !== -1) { |
|
1444 return ii; |
|
1445 } |
|
1446 ii = indexOf.call(this._weekdaysParse, llc); |
|
1447 if (ii !== -1) { |
|
1448 return ii; |
|
1449 } |
|
1450 ii = indexOf.call(this._shortWeekdaysParse, llc); |
|
1451 return ii !== -1 ? ii : null; |
|
1452 } |
|
1453 } |
|
1454 } |
|
1455 |
|
1456 function localeWeekdaysParse (weekdayName, format, strict) { |
|
1457 var i, mom, regex; |
|
1458 |
|
1459 if (this._weekdaysParseExact) { |
|
1460 return handleStrictParse$1.call(this, weekdayName, format, strict); |
|
1461 } |
|
1462 |
|
1463 if (!this._weekdaysParse) { |
|
1464 this._weekdaysParse = []; |
|
1465 this._minWeekdaysParse = []; |
|
1466 this._shortWeekdaysParse = []; |
|
1467 this._fullWeekdaysParse = []; |
|
1468 } |
|
1469 |
|
1470 for (i = 0; i < 7; i++) { |
|
1471 // make the regex if we don't have it already |
|
1472 |
|
1473 mom = createUTC([2000, 1]).day(i); |
|
1474 if (strict && !this._fullWeekdaysParse[i]) { |
|
1475 this._fullWeekdaysParse[i] = new RegExp('^' + this.weekdays(mom, '').replace('.', '\\.?') + '$', 'i'); |
|
1476 this._shortWeekdaysParse[i] = new RegExp('^' + this.weekdaysShort(mom, '').replace('.', '\\.?') + '$', 'i'); |
|
1477 this._minWeekdaysParse[i] = new RegExp('^' + this.weekdaysMin(mom, '').replace('.', '\\.?') + '$', 'i'); |
|
1478 } |
|
1479 if (!this._weekdaysParse[i]) { |
|
1480 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); |
|
1481 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); |
|
1482 } |
|
1483 // test the regex |
|
1484 if (strict && format === 'dddd' && this._fullWeekdaysParse[i].test(weekdayName)) { |
|
1485 return i; |
|
1486 } else if (strict && format === 'ddd' && this._shortWeekdaysParse[i].test(weekdayName)) { |
|
1487 return i; |
|
1488 } else if (strict && format === 'dd' && this._minWeekdaysParse[i].test(weekdayName)) { |
|
1489 return i; |
|
1490 } else if (!strict && this._weekdaysParse[i].test(weekdayName)) { |
|
1491 return i; |
|
1492 } |
|
1493 } |
|
1494 } |
|
1495 |
|
1496 // MOMENTS |
|
1497 |
|
1498 function getSetDayOfWeek (input) { |
|
1499 if (!this.isValid()) { |
|
1500 return input != null ? this : NaN; |
|
1501 } |
|
1502 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); |
|
1503 if (input != null) { |
|
1504 input = parseWeekday(input, this.localeData()); |
|
1505 return this.add(input - day, 'd'); |
|
1506 } else { |
|
1507 return day; |
|
1508 } |
|
1509 } |
|
1510 |
|
1511 function getSetLocaleDayOfWeek (input) { |
|
1512 if (!this.isValid()) { |
|
1513 return input != null ? this : NaN; |
|
1514 } |
|
1515 var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7; |
|
1516 return input == null ? weekday : this.add(input - weekday, 'd'); |
|
1517 } |
|
1518 |
|
1519 function getSetISODayOfWeek (input) { |
|
1520 if (!this.isValid()) { |
|
1521 return input != null ? this : NaN; |
|
1522 } |
|
1523 |
|
1524 // behaves the same as moment#day except |
|
1525 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) |
|
1526 // as a setter, sunday should belong to the previous week. |
|
1527 |
|
1528 if (input != null) { |
|
1529 var weekday = parseIsoWeekday(input, this.localeData()); |
|
1530 return this.day(this.day() % 7 ? weekday : weekday - 7); |
|
1531 } else { |
|
1532 return this.day() || 7; |
|
1533 } |
|
1534 } |
|
1535 |
|
1536 var defaultWeekdaysRegex = matchWord; |
|
1537 function weekdaysRegex (isStrict) { |
|
1538 if (this._weekdaysParseExact) { |
|
1539 if (!hasOwnProp(this, '_weekdaysRegex')) { |
|
1540 computeWeekdaysParse.call(this); |
|
1541 } |
|
1542 if (isStrict) { |
|
1543 return this._weekdaysStrictRegex; |
|
1544 } else { |
|
1545 return this._weekdaysRegex; |
|
1546 } |
|
1547 } else { |
|
1548 if (!hasOwnProp(this, '_weekdaysRegex')) { |
|
1549 this._weekdaysRegex = defaultWeekdaysRegex; |
|
1550 } |
|
1551 return this._weekdaysStrictRegex && isStrict ? |
|
1552 this._weekdaysStrictRegex : this._weekdaysRegex; |
|
1553 } |
|
1554 } |
|
1555 |
|
1556 var defaultWeekdaysShortRegex = matchWord; |
|
1557 function weekdaysShortRegex (isStrict) { |
|
1558 if (this._weekdaysParseExact) { |
|
1559 if (!hasOwnProp(this, '_weekdaysRegex')) { |
|
1560 computeWeekdaysParse.call(this); |
|
1561 } |
|
1562 if (isStrict) { |
|
1563 return this._weekdaysShortStrictRegex; |
|
1564 } else { |
|
1565 return this._weekdaysShortRegex; |
|
1566 } |
|
1567 } else { |
|
1568 if (!hasOwnProp(this, '_weekdaysShortRegex')) { |
|
1569 this._weekdaysShortRegex = defaultWeekdaysShortRegex; |
|
1570 } |
|
1571 return this._weekdaysShortStrictRegex && isStrict ? |
|
1572 this._weekdaysShortStrictRegex : this._weekdaysShortRegex; |
|
1573 } |
|
1574 } |
|
1575 |
|
1576 var defaultWeekdaysMinRegex = matchWord; |
|
1577 function weekdaysMinRegex (isStrict) { |
|
1578 if (this._weekdaysParseExact) { |
|
1579 if (!hasOwnProp(this, '_weekdaysRegex')) { |
|
1580 computeWeekdaysParse.call(this); |
|
1581 } |
|
1582 if (isStrict) { |
|
1583 return this._weekdaysMinStrictRegex; |
|
1584 } else { |
|
1585 return this._weekdaysMinRegex; |
|
1586 } |
|
1587 } else { |
|
1588 if (!hasOwnProp(this, '_weekdaysMinRegex')) { |
|
1589 this._weekdaysMinRegex = defaultWeekdaysMinRegex; |
|
1590 } |
|
1591 return this._weekdaysMinStrictRegex && isStrict ? |
|
1592 this._weekdaysMinStrictRegex : this._weekdaysMinRegex; |
|
1593 } |
|
1594 } |
|
1595 |
|
1596 |
|
1597 function computeWeekdaysParse () { |
|
1598 function cmpLenRev(a, b) { |
|
1599 return b.length - a.length; |
|
1600 } |
|
1601 |
|
1602 var minPieces = [], shortPieces = [], longPieces = [], mixedPieces = [], |
|
1603 i, mom, minp, shortp, longp; |
|
1604 for (i = 0; i < 7; i++) { |
|
1605 // make the regex if we don't have it already |
|
1606 mom = createUTC([2000, 1]).day(i); |
|
1607 minp = this.weekdaysMin(mom, ''); |
|
1608 shortp = this.weekdaysShort(mom, ''); |
|
1609 longp = this.weekdays(mom, ''); |
|
1610 minPieces.push(minp); |
|
1611 shortPieces.push(shortp); |
|
1612 longPieces.push(longp); |
|
1613 mixedPieces.push(minp); |
|
1614 mixedPieces.push(shortp); |
|
1615 mixedPieces.push(longp); |
|
1616 } |
|
1617 // Sorting makes sure if one weekday (or abbr) is a prefix of another it |
|
1618 // will match the longer piece. |
|
1619 minPieces.sort(cmpLenRev); |
|
1620 shortPieces.sort(cmpLenRev); |
|
1621 longPieces.sort(cmpLenRev); |
|
1622 mixedPieces.sort(cmpLenRev); |
|
1623 for (i = 0; i < 7; i++) { |
|
1624 shortPieces[i] = regexEscape(shortPieces[i]); |
|
1625 longPieces[i] = regexEscape(longPieces[i]); |
|
1626 mixedPieces[i] = regexEscape(mixedPieces[i]); |
|
1627 } |
|
1628 |
|
1629 this._weekdaysRegex = new RegExp('^(' + mixedPieces.join('|') + ')', 'i'); |
|
1630 this._weekdaysShortRegex = this._weekdaysRegex; |
|
1631 this._weekdaysMinRegex = this._weekdaysRegex; |
|
1632 |
|
1633 this._weekdaysStrictRegex = new RegExp('^(' + longPieces.join('|') + ')', 'i'); |
|
1634 this._weekdaysShortStrictRegex = new RegExp('^(' + shortPieces.join('|') + ')', 'i'); |
|
1635 this._weekdaysMinStrictRegex = new RegExp('^(' + minPieces.join('|') + ')', 'i'); |
|
1636 } |
|
1637 |
|
1638 // FORMATTING |
|
1639 |
|
1640 function hFormat() { |
|
1641 return this.hours() % 12 || 12; |
|
1642 } |
|
1643 |
|
1644 function kFormat() { |
|
1645 return this.hours() || 24; |
|
1646 } |
|
1647 |
|
1648 addFormatToken('H', ['HH', 2], 0, 'hour'); |
|
1649 addFormatToken('h', ['hh', 2], 0, hFormat); |
|
1650 addFormatToken('k', ['kk', 2], 0, kFormat); |
|
1651 |
|
1652 addFormatToken('hmm', 0, 0, function () { |
|
1653 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2); |
|
1654 }); |
|
1655 |
|
1656 addFormatToken('hmmss', 0, 0, function () { |
|
1657 return '' + hFormat.apply(this) + zeroFill(this.minutes(), 2) + |
|
1658 zeroFill(this.seconds(), 2); |
|
1659 }); |
|
1660 |
|
1661 addFormatToken('Hmm', 0, 0, function () { |
|
1662 return '' + this.hours() + zeroFill(this.minutes(), 2); |
|
1663 }); |
|
1664 |
|
1665 addFormatToken('Hmmss', 0, 0, function () { |
|
1666 return '' + this.hours() + zeroFill(this.minutes(), 2) + |
|
1667 zeroFill(this.seconds(), 2); |
|
1668 }); |
|
1669 |
|
1670 function meridiem (token, lowercase) { |
|
1671 addFormatToken(token, 0, 0, function () { |
|
1672 return this.localeData().meridiem(this.hours(), this.minutes(), lowercase); |
|
1673 }); |
|
1674 } |
|
1675 |
|
1676 meridiem('a', true); |
|
1677 meridiem('A', false); |
|
1678 |
|
1679 // ALIASES |
|
1680 |
|
1681 addUnitAlias('hour', 'h'); |
|
1682 |
|
1683 // PRIORITY |
|
1684 addUnitPriority('hour', 13); |
|
1685 |
|
1686 // PARSING |
|
1687 |
|
1688 function matchMeridiem (isStrict, locale) { |
|
1689 return locale._meridiemParse; |
|
1690 } |
|
1691 |
|
1692 addRegexToken('a', matchMeridiem); |
|
1693 addRegexToken('A', matchMeridiem); |
|
1694 addRegexToken('H', match1to2); |
|
1695 addRegexToken('h', match1to2); |
|
1696 addRegexToken('k', match1to2); |
|
1697 addRegexToken('HH', match1to2, match2); |
|
1698 addRegexToken('hh', match1to2, match2); |
|
1699 addRegexToken('kk', match1to2, match2); |
|
1700 |
|
1701 addRegexToken('hmm', match3to4); |
|
1702 addRegexToken('hmmss', match5to6); |
|
1703 addRegexToken('Hmm', match3to4); |
|
1704 addRegexToken('Hmmss', match5to6); |
|
1705 |
|
1706 addParseToken(['H', 'HH'], HOUR); |
|
1707 addParseToken(['k', 'kk'], function (input, array, config) { |
|
1708 var kInput = toInt(input); |
|
1709 array[HOUR] = kInput === 24 ? 0 : kInput; |
|
1710 }); |
|
1711 addParseToken(['a', 'A'], function (input, array, config) { |
|
1712 config._isPm = config._locale.isPM(input); |
|
1713 config._meridiem = input; |
|
1714 }); |
|
1715 addParseToken(['h', 'hh'], function (input, array, config) { |
|
1716 array[HOUR] = toInt(input); |
|
1717 getParsingFlags(config).bigHour = true; |
|
1718 }); |
|
1719 addParseToken('hmm', function (input, array, config) { |
|
1720 var pos = input.length - 2; |
|
1721 array[HOUR] = toInt(input.substr(0, pos)); |
|
1722 array[MINUTE] = toInt(input.substr(pos)); |
|
1723 getParsingFlags(config).bigHour = true; |
|
1724 }); |
|
1725 addParseToken('hmmss', function (input, array, config) { |
|
1726 var pos1 = input.length - 4; |
|
1727 var pos2 = input.length - 2; |
|
1728 array[HOUR] = toInt(input.substr(0, pos1)); |
|
1729 array[MINUTE] = toInt(input.substr(pos1, 2)); |
|
1730 array[SECOND] = toInt(input.substr(pos2)); |
|
1731 getParsingFlags(config).bigHour = true; |
|
1732 }); |
|
1733 addParseToken('Hmm', function (input, array, config) { |
|
1734 var pos = input.length - 2; |
|
1735 array[HOUR] = toInt(input.substr(0, pos)); |
|
1736 array[MINUTE] = toInt(input.substr(pos)); |
|
1737 }); |
|
1738 addParseToken('Hmmss', function (input, array, config) { |
|
1739 var pos1 = input.length - 4; |
|
1740 var pos2 = input.length - 2; |
|
1741 array[HOUR] = toInt(input.substr(0, pos1)); |
|
1742 array[MINUTE] = toInt(input.substr(pos1, 2)); |
|
1743 array[SECOND] = toInt(input.substr(pos2)); |
|
1744 }); |
|
1745 |
|
1746 // LOCALES |
|
1747 |
|
1748 function localeIsPM (input) { |
|
1749 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays |
|
1750 // Using charAt should be more compatible. |
|
1751 return ((input + '').toLowerCase().charAt(0) === 'p'); |
|
1752 } |
|
1753 |
|
1754 var defaultLocaleMeridiemParse = /[ap]\.?m?\.?/i; |
|
1755 function localeMeridiem (hours, minutes, isLower) { |
|
1756 if (hours > 11) { |
|
1757 return isLower ? 'pm' : 'PM'; |
|
1758 } else { |
|
1759 return isLower ? 'am' : 'AM'; |
|
1760 } |
|
1761 } |
|
1762 |
|
1763 |
|
1764 // MOMENTS |
|
1765 |
|
1766 // Setting the hour should keep the time, because the user explicitly |
|
1767 // specified which hour they want. So trying to maintain the same hour (in |
|
1768 // a new timezone) makes sense. Adding/subtracting hours does not follow |
|
1769 // this rule. |
|
1770 var getSetHour = makeGetSet('Hours', true); |
|
1771 |
|
1772 var baseConfig = { |
|
1773 calendar: defaultCalendar, |
|
1774 longDateFormat: defaultLongDateFormat, |
|
1775 invalidDate: defaultInvalidDate, |
|
1776 ordinal: defaultOrdinal, |
|
1777 dayOfMonthOrdinalParse: defaultDayOfMonthOrdinalParse, |
|
1778 relativeTime: defaultRelativeTime, |
|
1779 |
|
1780 months: defaultLocaleMonths, |
|
1781 monthsShort: defaultLocaleMonthsShort, |
|
1782 |
|
1783 week: defaultLocaleWeek, |
|
1784 |
|
1785 weekdays: defaultLocaleWeekdays, |
|
1786 weekdaysMin: defaultLocaleWeekdaysMin, |
|
1787 weekdaysShort: defaultLocaleWeekdaysShort, |
|
1788 |
|
1789 meridiemParse: defaultLocaleMeridiemParse |
|
1790 }; |
|
1791 |
|
1792 // internal storage for locale config files |
|
1793 var locales = {}; |
|
1794 var localeFamilies = {}; |
|
1795 var globalLocale; |
|
1796 |
|
1797 function normalizeLocale(key) { |
|
1798 return key ? key.toLowerCase().replace('_', '-') : key; |
|
1799 } |
|
1800 |
|
1801 // pick the locale from the array |
|
1802 // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each |
|
1803 // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root |
|
1804 function chooseLocale(names) { |
|
1805 var i = 0, j, next, locale, split; |
|
1806 |
|
1807 while (i < names.length) { |
|
1808 split = normalizeLocale(names[i]).split('-'); |
|
1809 j = split.length; |
|
1810 next = normalizeLocale(names[i + 1]); |
|
1811 next = next ? next.split('-') : null; |
|
1812 while (j > 0) { |
|
1813 locale = loadLocale(split.slice(0, j).join('-')); |
|
1814 if (locale) { |
|
1815 return locale; |
|
1816 } |
|
1817 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { |
|
1818 //the next array item is better than a shallower substring of this one |
|
1819 break; |
|
1820 } |
|
1821 j--; |
|
1822 } |
|
1823 i++; |
|
1824 } |
|
1825 return globalLocale; |
|
1826 } |
|
1827 |
|
1828 function loadLocale(name) { |
|
1829 var oldLocale = null; |
|
1830 // TODO: Find a better way to register and load all the locales in Node |
|
1831 if (!locales[name] && (typeof module !== 'undefined') && |
|
1832 module && module.exports) { |
|
1833 try { |
|
1834 oldLocale = globalLocale._abbr; |
|
1835 var aliasedRequire = require; |
|
1836 aliasedRequire('./locale/' + name); |
|
1837 getSetGlobalLocale(oldLocale); |
|
1838 } catch (e) {} |
|
1839 } |
|
1840 return locales[name]; |
|
1841 } |
|
1842 |
|
1843 // This function will load locale and then set the global locale. If |
|
1844 // no arguments are passed in, it will simply return the current global |
|
1845 // locale key. |
|
1846 function getSetGlobalLocale (key, values) { |
|
1847 var data; |
|
1848 if (key) { |
|
1849 if (isUndefined(values)) { |
|
1850 data = getLocale(key); |
|
1851 } |
|
1852 else { |
|
1853 data = defineLocale(key, values); |
|
1854 } |
|
1855 |
|
1856 if (data) { |
|
1857 // moment.duration._locale = moment._locale = data; |
|
1858 globalLocale = data; |
|
1859 } |
|
1860 else { |
|
1861 if ((typeof console !== 'undefined') && console.warn) { |
|
1862 //warn user if arguments are passed but the locale could not be set |
|
1863 console.warn('Locale ' + key + ' not found. Did you forget to load it?'); |
|
1864 } |
|
1865 } |
|
1866 } |
|
1867 |
|
1868 return globalLocale._abbr; |
|
1869 } |
|
1870 |
|
1871 function defineLocale (name, config) { |
|
1872 if (config !== null) { |
|
1873 var locale, parentConfig = baseConfig; |
|
1874 config.abbr = name; |
|
1875 if (locales[name] != null) { |
|
1876 deprecateSimple('defineLocaleOverride', |
|
1877 'use moment.updateLocale(localeName, config) to change ' + |
|
1878 'an existing locale. moment.defineLocale(localeName, ' + |
|
1879 'config) should only be used for creating a new locale ' + |
|
1880 'See http://momentjs.com/guides/#/warnings/define-locale/ for more info.'); |
|
1881 parentConfig = locales[name]._config; |
|
1882 } else if (config.parentLocale != null) { |
|
1883 if (locales[config.parentLocale] != null) { |
|
1884 parentConfig = locales[config.parentLocale]._config; |
|
1885 } else { |
|
1886 locale = loadLocale(config.parentLocale); |
|
1887 if (locale != null) { |
|
1888 parentConfig = locale._config; |
|
1889 } else { |
|
1890 if (!localeFamilies[config.parentLocale]) { |
|
1891 localeFamilies[config.parentLocale] = []; |
|
1892 } |
|
1893 localeFamilies[config.parentLocale].push({ |
|
1894 name: name, |
|
1895 config: config |
|
1896 }); |
|
1897 return null; |
|
1898 } |
|
1899 } |
|
1900 } |
|
1901 locales[name] = new Locale(mergeConfigs(parentConfig, config)); |
|
1902 |
|
1903 if (localeFamilies[name]) { |
|
1904 localeFamilies[name].forEach(function (x) { |
|
1905 defineLocale(x.name, x.config); |
|
1906 }); |
|
1907 } |
|
1908 |
|
1909 // backwards compat for now: also set the locale |
|
1910 // make sure we set the locale AFTER all child locales have been |
|
1911 // created, so we won't end up with the child locale set. |
|
1912 getSetGlobalLocale(name); |
|
1913 |
|
1914 |
|
1915 return locales[name]; |
|
1916 } else { |
|
1917 // useful for testing |
|
1918 delete locales[name]; |
|
1919 return null; |
|
1920 } |
|
1921 } |
|
1922 |
|
1923 function updateLocale(name, config) { |
|
1924 if (config != null) { |
|
1925 var locale, tmpLocale, parentConfig = baseConfig; |
|
1926 // MERGE |
|
1927 tmpLocale = loadLocale(name); |
|
1928 if (tmpLocale != null) { |
|
1929 parentConfig = tmpLocale._config; |
|
1930 } |
|
1931 config = mergeConfigs(parentConfig, config); |
|
1932 locale = new Locale(config); |
|
1933 locale.parentLocale = locales[name]; |
|
1934 locales[name] = locale; |
|
1935 |
|
1936 // backwards compat for now: also set the locale |
|
1937 getSetGlobalLocale(name); |
|
1938 } else { |
|
1939 // pass null for config to unupdate, useful for tests |
|
1940 if (locales[name] != null) { |
|
1941 if (locales[name].parentLocale != null) { |
|
1942 locales[name] = locales[name].parentLocale; |
|
1943 } else if (locales[name] != null) { |
|
1944 delete locales[name]; |
|
1945 } |
|
1946 } |
|
1947 } |
|
1948 return locales[name]; |
|
1949 } |
|
1950 |
|
1951 // returns locale data |
|
1952 function getLocale (key) { |
|
1953 var locale; |
|
1954 |
|
1955 if (key && key._locale && key._locale._abbr) { |
|
1956 key = key._locale._abbr; |
|
1957 } |
|
1958 |
|
1959 if (!key) { |
|
1960 return globalLocale; |
|
1961 } |
|
1962 |
|
1963 if (!isArray(key)) { |
|
1964 //short-circuit everything else |
|
1965 locale = loadLocale(key); |
|
1966 if (locale) { |
|
1967 return locale; |
|
1968 } |
|
1969 key = [key]; |
|
1970 } |
|
1971 |
|
1972 return chooseLocale(key); |
|
1973 } |
|
1974 |
|
1975 function listLocales() { |
|
1976 return keys(locales); |
|
1977 } |
|
1978 |
|
1979 function checkOverflow (m) { |
|
1980 var overflow; |
|
1981 var a = m._a; |
|
1982 |
|
1983 if (a && getParsingFlags(m).overflow === -2) { |
|
1984 overflow = |
|
1985 a[MONTH] < 0 || a[MONTH] > 11 ? MONTH : |
|
1986 a[DATE] < 1 || a[DATE] > daysInMonth(a[YEAR], a[MONTH]) ? DATE : |
|
1987 a[HOUR] < 0 || a[HOUR] > 24 || (a[HOUR] === 24 && (a[MINUTE] !== 0 || a[SECOND] !== 0 || a[MILLISECOND] !== 0)) ? HOUR : |
|
1988 a[MINUTE] < 0 || a[MINUTE] > 59 ? MINUTE : |
|
1989 a[SECOND] < 0 || a[SECOND] > 59 ? SECOND : |
|
1990 a[MILLISECOND] < 0 || a[MILLISECOND] > 999 ? MILLISECOND : |
|
1991 -1; |
|
1992 |
|
1993 if (getParsingFlags(m)._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { |
|
1994 overflow = DATE; |
|
1995 } |
|
1996 if (getParsingFlags(m)._overflowWeeks && overflow === -1) { |
|
1997 overflow = WEEK; |
|
1998 } |
|
1999 if (getParsingFlags(m)._overflowWeekday && overflow === -1) { |
|
2000 overflow = WEEKDAY; |
|
2001 } |
|
2002 |
|
2003 getParsingFlags(m).overflow = overflow; |
|
2004 } |
|
2005 |
|
2006 return m; |
|
2007 } |
|
2008 |
|
2009 // Pick the first defined of two or three arguments. |
|
2010 function defaults(a, b, c) { |
|
2011 if (a != null) { |
|
2012 return a; |
|
2013 } |
|
2014 if (b != null) { |
|
2015 return b; |
|
2016 } |
|
2017 return c; |
|
2018 } |
|
2019 |
|
2020 function currentDateArray(config) { |
|
2021 // hooks is actually the exported moment object |
|
2022 var nowValue = new Date(hooks.now()); |
|
2023 if (config._useUTC) { |
|
2024 return [nowValue.getUTCFullYear(), nowValue.getUTCMonth(), nowValue.getUTCDate()]; |
|
2025 } |
|
2026 return [nowValue.getFullYear(), nowValue.getMonth(), nowValue.getDate()]; |
|
2027 } |
|
2028 |
|
2029 // convert an array to a date. |
|
2030 // the array should mirror the parameters below |
|
2031 // note: all values past the year are optional and will default to the lowest possible value. |
|
2032 // [year, month, day , hour, minute, second, millisecond] |
|
2033 function configFromArray (config) { |
|
2034 var i, date, input = [], currentDate, expectedWeekday, yearToUse; |
|
2035 |
|
2036 if (config._d) { |
|
2037 return; |
|
2038 } |
|
2039 |
|
2040 currentDate = currentDateArray(config); |
|
2041 |
|
2042 //compute day of the year from weeks and weekdays |
|
2043 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { |
|
2044 dayOfYearFromWeekInfo(config); |
|
2045 } |
|
2046 |
|
2047 //if the day of the year is set, figure out what it is |
|
2048 if (config._dayOfYear != null) { |
|
2049 yearToUse = defaults(config._a[YEAR], currentDate[YEAR]); |
|
2050 |
|
2051 if (config._dayOfYear > daysInYear(yearToUse) || config._dayOfYear === 0) { |
|
2052 getParsingFlags(config)._overflowDayOfYear = true; |
|
2053 } |
|
2054 |
|
2055 date = createUTCDate(yearToUse, 0, config._dayOfYear); |
|
2056 config._a[MONTH] = date.getUTCMonth(); |
|
2057 config._a[DATE] = date.getUTCDate(); |
|
2058 } |
|
2059 |
|
2060 // Default to current date. |
|
2061 // * if no year, month, day of month are given, default to today |
|
2062 // * if day of month is given, default month and year |
|
2063 // * if month is given, default only year |
|
2064 // * if year is given, don't default anything |
|
2065 for (i = 0; i < 3 && config._a[i] == null; ++i) { |
|
2066 config._a[i] = input[i] = currentDate[i]; |
|
2067 } |
|
2068 |
|
2069 // Zero out whatever was not defaulted, including time |
|
2070 for (; i < 7; i++) { |
|
2071 config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; |
|
2072 } |
|
2073 |
|
2074 // Check for 24:00:00.000 |
|
2075 if (config._a[HOUR] === 24 && |
|
2076 config._a[MINUTE] === 0 && |
|
2077 config._a[SECOND] === 0 && |
|
2078 config._a[MILLISECOND] === 0) { |
|
2079 config._nextDay = true; |
|
2080 config._a[HOUR] = 0; |
|
2081 } |
|
2082 |
|
2083 config._d = (config._useUTC ? createUTCDate : createDate).apply(null, input); |
|
2084 expectedWeekday = config._useUTC ? config._d.getUTCDay() : config._d.getDay(); |
|
2085 |
|
2086 // Apply timezone offset from input. The actual utcOffset can be changed |
|
2087 // with parseZone. |
|
2088 if (config._tzm != null) { |
|
2089 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); |
|
2090 } |
|
2091 |
|
2092 if (config._nextDay) { |
|
2093 config._a[HOUR] = 24; |
|
2094 } |
|
2095 |
|
2096 // check for mismatching day of week |
|
2097 if (config._w && typeof config._w.d !== 'undefined' && config._w.d !== expectedWeekday) { |
|
2098 getParsingFlags(config).weekdayMismatch = true; |
|
2099 } |
|
2100 } |
|
2101 |
|
2102 function dayOfYearFromWeekInfo(config) { |
|
2103 var w, weekYear, week, weekday, dow, doy, temp, weekdayOverflow; |
|
2104 |
|
2105 w = config._w; |
|
2106 if (w.GG != null || w.W != null || w.E != null) { |
|
2107 dow = 1; |
|
2108 doy = 4; |
|
2109 |
|
2110 // TODO: We need to take the current isoWeekYear, but that depends on |
|
2111 // how we interpret now (local, utc, fixed offset). So create |
|
2112 // a now version of current config (take local/utc/offset flags, and |
|
2113 // create now). |
|
2114 weekYear = defaults(w.GG, config._a[YEAR], weekOfYear(createLocal(), 1, 4).year); |
|
2115 week = defaults(w.W, 1); |
|
2116 weekday = defaults(w.E, 1); |
|
2117 if (weekday < 1 || weekday > 7) { |
|
2118 weekdayOverflow = true; |
|
2119 } |
|
2120 } else { |
|
2121 dow = config._locale._week.dow; |
|
2122 doy = config._locale._week.doy; |
|
2123 |
|
2124 var curWeek = weekOfYear(createLocal(), dow, doy); |
|
2125 |
|
2126 weekYear = defaults(w.gg, config._a[YEAR], curWeek.year); |
|
2127 |
|
2128 // Default to current week. |
|
2129 week = defaults(w.w, curWeek.week); |
|
2130 |
|
2131 if (w.d != null) { |
|
2132 // weekday -- low day numbers are considered next week |
|
2133 weekday = w.d; |
|
2134 if (weekday < 0 || weekday > 6) { |
|
2135 weekdayOverflow = true; |
|
2136 } |
|
2137 } else if (w.e != null) { |
|
2138 // local weekday -- counting starts from begining of week |
|
2139 weekday = w.e + dow; |
|
2140 if (w.e < 0 || w.e > 6) { |
|
2141 weekdayOverflow = true; |
|
2142 } |
|
2143 } else { |
|
2144 // default to begining of week |
|
2145 weekday = dow; |
|
2146 } |
|
2147 } |
|
2148 if (week < 1 || week > weeksInYear(weekYear, dow, doy)) { |
|
2149 getParsingFlags(config)._overflowWeeks = true; |
|
2150 } else if (weekdayOverflow != null) { |
|
2151 getParsingFlags(config)._overflowWeekday = true; |
|
2152 } else { |
|
2153 temp = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy); |
|
2154 config._a[YEAR] = temp.year; |
|
2155 config._dayOfYear = temp.dayOfYear; |
|
2156 } |
|
2157 } |
|
2158 |
|
2159 // iso 8601 regex |
|
2160 // 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 or +00) |
|
2161 var extendedIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; |
|
2162 var basicIsoRegex = /^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/; |
|
2163 |
|
2164 var tzRegex = /Z|[+-]\d\d(?::?\d\d)?/; |
|
2165 |
|
2166 var isoDates = [ |
|
2167 ['YYYYYY-MM-DD', /[+-]\d{6}-\d\d-\d\d/], |
|
2168 ['YYYY-MM-DD', /\d{4}-\d\d-\d\d/], |
|
2169 ['GGGG-[W]WW-E', /\d{4}-W\d\d-\d/], |
|
2170 ['GGGG-[W]WW', /\d{4}-W\d\d/, false], |
|
2171 ['YYYY-DDD', /\d{4}-\d{3}/], |
|
2172 ['YYYY-MM', /\d{4}-\d\d/, false], |
|
2173 ['YYYYYYMMDD', /[+-]\d{10}/], |
|
2174 ['YYYYMMDD', /\d{8}/], |
|
2175 // YYYYMM is NOT allowed by the standard |
|
2176 ['GGGG[W]WWE', /\d{4}W\d{3}/], |
|
2177 ['GGGG[W]WW', /\d{4}W\d{2}/, false], |
|
2178 ['YYYYDDD', /\d{7}/] |
|
2179 ]; |
|
2180 |
|
2181 // iso time formats and regexes |
|
2182 var isoTimes = [ |
|
2183 ['HH:mm:ss.SSSS', /\d\d:\d\d:\d\d\.\d+/], |
|
2184 ['HH:mm:ss,SSSS', /\d\d:\d\d:\d\d,\d+/], |
|
2185 ['HH:mm:ss', /\d\d:\d\d:\d\d/], |
|
2186 ['HH:mm', /\d\d:\d\d/], |
|
2187 ['HHmmss.SSSS', /\d\d\d\d\d\d\.\d+/], |
|
2188 ['HHmmss,SSSS', /\d\d\d\d\d\d,\d+/], |
|
2189 ['HHmmss', /\d\d\d\d\d\d/], |
|
2190 ['HHmm', /\d\d\d\d/], |
|
2191 ['HH', /\d\d/] |
|
2192 ]; |
|
2193 |
|
2194 var aspNetJsonRegex = /^\/?Date\((\-?\d+)/i; |
|
2195 |
|
2196 // date from iso format |
|
2197 function configFromISO(config) { |
|
2198 var i, l, |
|
2199 string = config._i, |
|
2200 match = extendedIsoRegex.exec(string) || basicIsoRegex.exec(string), |
|
2201 allowTime, dateFormat, timeFormat, tzFormat; |
|
2202 |
|
2203 if (match) { |
|
2204 getParsingFlags(config).iso = true; |
|
2205 |
|
2206 for (i = 0, l = isoDates.length; i < l; i++) { |
|
2207 if (isoDates[i][1].exec(match[1])) { |
|
2208 dateFormat = isoDates[i][0]; |
|
2209 allowTime = isoDates[i][2] !== false; |
|
2210 break; |
|
2211 } |
|
2212 } |
|
2213 if (dateFormat == null) { |
|
2214 config._isValid = false; |
|
2215 return; |
|
2216 } |
|
2217 if (match[3]) { |
|
2218 for (i = 0, l = isoTimes.length; i < l; i++) { |
|
2219 if (isoTimes[i][1].exec(match[3])) { |
|
2220 // match[2] should be 'T' or space |
|
2221 timeFormat = (match[2] || ' ') + isoTimes[i][0]; |
|
2222 break; |
|
2223 } |
|
2224 } |
|
2225 if (timeFormat == null) { |
|
2226 config._isValid = false; |
|
2227 return; |
|
2228 } |
|
2229 } |
|
2230 if (!allowTime && timeFormat != null) { |
|
2231 config._isValid = false; |
|
2232 return; |
|
2233 } |
|
2234 if (match[4]) { |
|
2235 if (tzRegex.exec(match[4])) { |
|
2236 tzFormat = 'Z'; |
|
2237 } else { |
|
2238 config._isValid = false; |
|
2239 return; |
|
2240 } |
|
2241 } |
|
2242 config._f = dateFormat + (timeFormat || '') + (tzFormat || ''); |
|
2243 configFromStringAndFormat(config); |
|
2244 } else { |
|
2245 config._isValid = false; |
|
2246 } |
|
2247 } |
|
2248 |
|
2249 // RFC 2822 regex: For details see https://tools.ietf.org/html/rfc2822#section-3.3 |
|
2250 var rfc2822 = /^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/; |
|
2251 |
|
2252 function extractFromRFC2822Strings(yearStr, monthStr, dayStr, hourStr, minuteStr, secondStr) { |
|
2253 var result = [ |
|
2254 untruncateYear(yearStr), |
|
2255 defaultLocaleMonthsShort.indexOf(monthStr), |
|
2256 parseInt(dayStr, 10), |
|
2257 parseInt(hourStr, 10), |
|
2258 parseInt(minuteStr, 10) |
|
2259 ]; |
|
2260 |
|
2261 if (secondStr) { |
|
2262 result.push(parseInt(secondStr, 10)); |
|
2263 } |
|
2264 |
|
2265 return result; |
|
2266 } |
|
2267 |
|
2268 function untruncateYear(yearStr) { |
|
2269 var year = parseInt(yearStr, 10); |
|
2270 if (year <= 49) { |
|
2271 return 2000 + year; |
|
2272 } else if (year <= 999) { |
|
2273 return 1900 + year; |
|
2274 } |
|
2275 return year; |
|
2276 } |
|
2277 |
|
2278 function preprocessRFC2822(s) { |
|
2279 // Remove comments and folding whitespace and replace multiple-spaces with a single space |
|
2280 return s.replace(/\([^)]*\)|[\n\t]/g, ' ').replace(/(\s\s+)/g, ' ').replace(/^\s\s*/, '').replace(/\s\s*$/, ''); |
|
2281 } |
|
2282 |
|
2283 function checkWeekday(weekdayStr, parsedInput, config) { |
|
2284 if (weekdayStr) { |
|
2285 // TODO: Replace the vanilla JS Date object with an indepentent day-of-week check. |
|
2286 var weekdayProvided = defaultLocaleWeekdaysShort.indexOf(weekdayStr), |
|
2287 weekdayActual = new Date(parsedInput[0], parsedInput[1], parsedInput[2]).getDay(); |
|
2288 if (weekdayProvided !== weekdayActual) { |
|
2289 getParsingFlags(config).weekdayMismatch = true; |
|
2290 config._isValid = false; |
|
2291 return false; |
|
2292 } |
|
2293 } |
|
2294 return true; |
|
2295 } |
|
2296 |
|
2297 var obsOffsets = { |
|
2298 UT: 0, |
|
2299 GMT: 0, |
|
2300 EDT: -4 * 60, |
|
2301 EST: -5 * 60, |
|
2302 CDT: -5 * 60, |
|
2303 CST: -6 * 60, |
|
2304 MDT: -6 * 60, |
|
2305 MST: -7 * 60, |
|
2306 PDT: -7 * 60, |
|
2307 PST: -8 * 60 |
|
2308 }; |
|
2309 |
|
2310 function calculateOffset(obsOffset, militaryOffset, numOffset) { |
|
2311 if (obsOffset) { |
|
2312 return obsOffsets[obsOffset]; |
|
2313 } else if (militaryOffset) { |
|
2314 // the only allowed military tz is Z |
|
2315 return 0; |
|
2316 } else { |
|
2317 var hm = parseInt(numOffset, 10); |
|
2318 var m = hm % 100, h = (hm - m) / 100; |
|
2319 return h * 60 + m; |
|
2320 } |
|
2321 } |
|
2322 |
|
2323 // date and time from ref 2822 format |
|
2324 function configFromRFC2822(config) { |
|
2325 var match = rfc2822.exec(preprocessRFC2822(config._i)); |
|
2326 if (match) { |
|
2327 var parsedArray = extractFromRFC2822Strings(match[4], match[3], match[2], match[5], match[6], match[7]); |
|
2328 if (!checkWeekday(match[1], parsedArray, config)) { |
|
2329 return; |
|
2330 } |
|
2331 |
|
2332 config._a = parsedArray; |
|
2333 config._tzm = calculateOffset(match[8], match[9], match[10]); |
|
2334 |
|
2335 config._d = createUTCDate.apply(null, config._a); |
|
2336 config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm); |
|
2337 |
|
2338 getParsingFlags(config).rfc2822 = true; |
|
2339 } else { |
|
2340 config._isValid = false; |
|
2341 } |
|
2342 } |
|
2343 |
|
2344 // date from iso format or fallback |
|
2345 function configFromString(config) { |
|
2346 var matched = aspNetJsonRegex.exec(config._i); |
|
2347 |
|
2348 if (matched !== null) { |
|
2349 config._d = new Date(+matched[1]); |
|
2350 return; |
|
2351 } |
|
2352 |
|
2353 configFromISO(config); |
|
2354 if (config._isValid === false) { |
|
2355 delete config._isValid; |
|
2356 } else { |
|
2357 return; |
|
2358 } |
|
2359 |
|
2360 configFromRFC2822(config); |
|
2361 if (config._isValid === false) { |
|
2362 delete config._isValid; |
|
2363 } else { |
|
2364 return; |
|
2365 } |
|
2366 |
|
2367 // Final attempt, use Input Fallback |
|
2368 hooks.createFromInputFallback(config); |
|
2369 } |
|
2370 |
|
2371 hooks.createFromInputFallback = deprecate( |
|
2372 'value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), ' + |
|
2373 'which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are ' + |
|
2374 'discouraged and will be removed in an upcoming major release. Please refer to ' + |
|
2375 'http://momentjs.com/guides/#/warnings/js-date/ for more info.', |
|
2376 function (config) { |
|
2377 config._d = new Date(config._i + (config._useUTC ? ' UTC' : '')); |
|
2378 } |
|
2379 ); |
|
2380 |
|
2381 // constant that refers to the ISO standard |
|
2382 hooks.ISO_8601 = function () {}; |
|
2383 |
|
2384 // constant that refers to the RFC 2822 form |
|
2385 hooks.RFC_2822 = function () {}; |
|
2386 |
|
2387 // date from string and format string |
|
2388 function configFromStringAndFormat(config) { |
|
2389 // TODO: Move this to another part of the creation flow to prevent circular deps |
|
2390 if (config._f === hooks.ISO_8601) { |
|
2391 configFromISO(config); |
|
2392 return; |
|
2393 } |
|
2394 if (config._f === hooks.RFC_2822) { |
|
2395 configFromRFC2822(config); |
|
2396 return; |
|
2397 } |
|
2398 config._a = []; |
|
2399 getParsingFlags(config).empty = true; |
|
2400 |
|
2401 // This array is used to make a Date, either with `new Date` or `Date.UTC` |
|
2402 var string = '' + config._i, |
|
2403 i, parsedInput, tokens, token, skipped, |
|
2404 stringLength = string.length, |
|
2405 totalParsedInputLength = 0; |
|
2406 |
|
2407 tokens = expandFormat(config._f, config._locale).match(formattingTokens) || []; |
|
2408 |
|
2409 for (i = 0; i < tokens.length; i++) { |
|
2410 token = tokens[i]; |
|
2411 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; |
|
2412 // console.log('token', token, 'parsedInput', parsedInput, |
|
2413 // 'regex', getParseRegexForToken(token, config)); |
|
2414 if (parsedInput) { |
|
2415 skipped = string.substr(0, string.indexOf(parsedInput)); |
|
2416 if (skipped.length > 0) { |
|
2417 getParsingFlags(config).unusedInput.push(skipped); |
|
2418 } |
|
2419 string = string.slice(string.indexOf(parsedInput) + parsedInput.length); |
|
2420 totalParsedInputLength += parsedInput.length; |
|
2421 } |
|
2422 // don't parse if it's not a known token |
|
2423 if (formatTokenFunctions[token]) { |
|
2424 if (parsedInput) { |
|
2425 getParsingFlags(config).empty = false; |
|
2426 } |
|
2427 else { |
|
2428 getParsingFlags(config).unusedTokens.push(token); |
|
2429 } |
|
2430 addTimeToArrayFromToken(token, parsedInput, config); |
|
2431 } |
|
2432 else if (config._strict && !parsedInput) { |
|
2433 getParsingFlags(config).unusedTokens.push(token); |
|
2434 } |
|
2435 } |
|
2436 |
|
2437 // add remaining unparsed input length to the string |
|
2438 getParsingFlags(config).charsLeftOver = stringLength - totalParsedInputLength; |
|
2439 if (string.length > 0) { |
|
2440 getParsingFlags(config).unusedInput.push(string); |
|
2441 } |
|
2442 |
|
2443 // clear _12h flag if hour is <= 12 |
|
2444 if (config._a[HOUR] <= 12 && |
|
2445 getParsingFlags(config).bigHour === true && |
|
2446 config._a[HOUR] > 0) { |
|
2447 getParsingFlags(config).bigHour = undefined; |
|
2448 } |
|
2449 |
|
2450 getParsingFlags(config).parsedDateParts = config._a.slice(0); |
|
2451 getParsingFlags(config).meridiem = config._meridiem; |
|
2452 // handle meridiem |
|
2453 config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR], config._meridiem); |
|
2454 |
|
2455 configFromArray(config); |
|
2456 checkOverflow(config); |
|
2457 } |
|
2458 |
|
2459 |
|
2460 function meridiemFixWrap (locale, hour, meridiem) { |
|
2461 var isPm; |
|
2462 |
|
2463 if (meridiem == null) { |
|
2464 // nothing to do |
|
2465 return hour; |
|
2466 } |
|
2467 if (locale.meridiemHour != null) { |
|
2468 return locale.meridiemHour(hour, meridiem); |
|
2469 } else if (locale.isPM != null) { |
|
2470 // Fallback |
|
2471 isPm = locale.isPM(meridiem); |
|
2472 if (isPm && hour < 12) { |
|
2473 hour += 12; |
|
2474 } |
|
2475 if (!isPm && hour === 12) { |
|
2476 hour = 0; |
|
2477 } |
|
2478 return hour; |
|
2479 } else { |
|
2480 // this is not supposed to happen |
|
2481 return hour; |
|
2482 } |
|
2483 } |
|
2484 |
|
2485 // date from string and array of format strings |
|
2486 function configFromStringAndArray(config) { |
|
2487 var tempConfig, |
|
2488 bestMoment, |
|
2489 |
|
2490 scoreToBeat, |
|
2491 i, |
|
2492 currentScore; |
|
2493 |
|
2494 if (config._f.length === 0) { |
|
2495 getParsingFlags(config).invalidFormat = true; |
|
2496 config._d = new Date(NaN); |
|
2497 return; |
|
2498 } |
|
2499 |
|
2500 for (i = 0; i < config._f.length; i++) { |
|
2501 currentScore = 0; |
|
2502 tempConfig = copyConfig({}, config); |
|
2503 if (config._useUTC != null) { |
|
2504 tempConfig._useUTC = config._useUTC; |
|
2505 } |
|
2506 tempConfig._f = config._f[i]; |
|
2507 configFromStringAndFormat(tempConfig); |
|
2508 |
|
2509 if (!isValid(tempConfig)) { |
|
2510 continue; |
|
2511 } |
|
2512 |
|
2513 // if there is any input that was not parsed add a penalty for that format |
|
2514 currentScore += getParsingFlags(tempConfig).charsLeftOver; |
|
2515 |
|
2516 //or tokens |
|
2517 currentScore += getParsingFlags(tempConfig).unusedTokens.length * 10; |
|
2518 |
|
2519 getParsingFlags(tempConfig).score = currentScore; |
|
2520 |
|
2521 if (scoreToBeat == null || currentScore < scoreToBeat) { |
|
2522 scoreToBeat = currentScore; |
|
2523 bestMoment = tempConfig; |
|
2524 } |
|
2525 } |
|
2526 |
|
2527 extend(config, bestMoment || tempConfig); |
|
2528 } |
|
2529 |
|
2530 function configFromObject(config) { |
|
2531 if (config._d) { |
|
2532 return; |
|
2533 } |
|
2534 |
|
2535 var i = normalizeObjectUnits(config._i); |
|
2536 config._a = map([i.year, i.month, i.day || i.date, i.hour, i.minute, i.second, i.millisecond], function (obj) { |
|
2537 return obj && parseInt(obj, 10); |
|
2538 }); |
|
2539 |
|
2540 configFromArray(config); |
|
2541 } |
|
2542 |
|
2543 function createFromConfig (config) { |
|
2544 var res = new Moment(checkOverflow(prepareConfig(config))); |
|
2545 if (res._nextDay) { |
|
2546 // Adding is smart enough around DST |
|
2547 res.add(1, 'd'); |
|
2548 res._nextDay = undefined; |
|
2549 } |
|
2550 |
|
2551 return res; |
|
2552 } |
|
2553 |
|
2554 function prepareConfig (config) { |
|
2555 var input = config._i, |
|
2556 format = config._f; |
|
2557 |
|
2558 config._locale = config._locale || getLocale(config._l); |
|
2559 |
|
2560 if (input === null || (format === undefined && input === '')) { |
|
2561 return createInvalid({nullInput: true}); |
|
2562 } |
|
2563 |
|
2564 if (typeof input === 'string') { |
|
2565 config._i = input = config._locale.preparse(input); |
|
2566 } |
|
2567 |
|
2568 if (isMoment(input)) { |
|
2569 return new Moment(checkOverflow(input)); |
|
2570 } else if (isDate(input)) { |
|
2571 config._d = input; |
|
2572 } else if (isArray(format)) { |
|
2573 configFromStringAndArray(config); |
|
2574 } else if (format) { |
|
2575 configFromStringAndFormat(config); |
|
2576 } else { |
|
2577 configFromInput(config); |
|
2578 } |
|
2579 |
|
2580 if (!isValid(config)) { |
|
2581 config._d = null; |
|
2582 } |
|
2583 |
|
2584 return config; |
|
2585 } |
|
2586 |
|
2587 function configFromInput(config) { |
|
2588 var input = config._i; |
|
2589 if (isUndefined(input)) { |
|
2590 config._d = new Date(hooks.now()); |
|
2591 } else if (isDate(input)) { |
|
2592 config._d = new Date(input.valueOf()); |
|
2593 } else if (typeof input === 'string') { |
|
2594 configFromString(config); |
|
2595 } else if (isArray(input)) { |
|
2596 config._a = map(input.slice(0), function (obj) { |
|
2597 return parseInt(obj, 10); |
|
2598 }); |
|
2599 configFromArray(config); |
|
2600 } else if (isObject(input)) { |
|
2601 configFromObject(config); |
|
2602 } else if (isNumber(input)) { |
|
2603 // from milliseconds |
|
2604 config._d = new Date(input); |
|
2605 } else { |
|
2606 hooks.createFromInputFallback(config); |
|
2607 } |
|
2608 } |
|
2609 |
|
2610 function createLocalOrUTC (input, format, locale, strict, isUTC) { |
|
2611 var c = {}; |
|
2612 |
|
2613 if (locale === true || locale === false) { |
|
2614 strict = locale; |
|
2615 locale = undefined; |
|
2616 } |
|
2617 |
|
2618 if ((isObject(input) && isObjectEmpty(input)) || |
|
2619 (isArray(input) && input.length === 0)) { |
|
2620 input = undefined; |
|
2621 } |
|
2622 // object construction must be done this way. |
|
2623 // https://github.com/moment/moment/issues/1423 |
|
2624 c._isAMomentObject = true; |
|
2625 c._useUTC = c._isUTC = isUTC; |
|
2626 c._l = locale; |
|
2627 c._i = input; |
|
2628 c._f = format; |
|
2629 c._strict = strict; |
|
2630 |
|
2631 return createFromConfig(c); |
|
2632 } |
|
2633 |
|
2634 function createLocal (input, format, locale, strict) { |
|
2635 return createLocalOrUTC(input, format, locale, strict, false); |
|
2636 } |
|
2637 |
|
2638 var prototypeMin = deprecate( |
|
2639 'moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/', |
|
2640 function () { |
|
2641 var other = createLocal.apply(null, arguments); |
|
2642 if (this.isValid() && other.isValid()) { |
|
2643 return other < this ? this : other; |
|
2644 } else { |
|
2645 return createInvalid(); |
|
2646 } |
|
2647 } |
|
2648 ); |
|
2649 |
|
2650 var prototypeMax = deprecate( |
|
2651 'moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/', |
|
2652 function () { |
|
2653 var other = createLocal.apply(null, arguments); |
|
2654 if (this.isValid() && other.isValid()) { |
|
2655 return other > this ? this : other; |
|
2656 } else { |
|
2657 return createInvalid(); |
|
2658 } |
|
2659 } |
|
2660 ); |
|
2661 |
|
2662 // Pick a moment m from moments so that m[fn](other) is true for all |
|
2663 // other. This relies on the function fn to be transitive. |
|
2664 // |
|
2665 // moments should either be an array of moment objects or an array, whose |
|
2666 // first element is an array of moment objects. |
|
2667 function pickBy(fn, moments) { |
|
2668 var res, i; |
|
2669 if (moments.length === 1 && isArray(moments[0])) { |
|
2670 moments = moments[0]; |
|
2671 } |
|
2672 if (!moments.length) { |
|
2673 return createLocal(); |
|
2674 } |
|
2675 res = moments[0]; |
|
2676 for (i = 1; i < moments.length; ++i) { |
|
2677 if (!moments[i].isValid() || moments[i][fn](res)) { |
|
2678 res = moments[i]; |
|
2679 } |
|
2680 } |
|
2681 return res; |
|
2682 } |
|
2683 |
|
2684 // TODO: Use [].sort instead? |
|
2685 function min () { |
|
2686 var args = [].slice.call(arguments, 0); |
|
2687 |
|
2688 return pickBy('isBefore', args); |
|
2689 } |
|
2690 |
|
2691 function max () { |
|
2692 var args = [].slice.call(arguments, 0); |
|
2693 |
|
2694 return pickBy('isAfter', args); |
|
2695 } |
|
2696 |
|
2697 var now = function () { |
|
2698 return Date.now ? Date.now() : +(new Date()); |
|
2699 }; |
|
2700 |
|
2701 var ordering = ['year', 'quarter', 'month', 'week', 'day', 'hour', 'minute', 'second', 'millisecond']; |
|
2702 |
|
2703 function isDurationValid(m) { |
|
2704 for (var key in m) { |
|
2705 if (!(indexOf.call(ordering, key) !== -1 && (m[key] == null || !isNaN(m[key])))) { |
|
2706 return false; |
|
2707 } |
|
2708 } |
|
2709 |
|
2710 var unitHasDecimal = false; |
|
2711 for (var i = 0; i < ordering.length; ++i) { |
|
2712 if (m[ordering[i]]) { |
|
2713 if (unitHasDecimal) { |
|
2714 return false; // only allow non-integers for smallest unit |
|
2715 } |
|
2716 if (parseFloat(m[ordering[i]]) !== toInt(m[ordering[i]])) { |
|
2717 unitHasDecimal = true; |
|
2718 } |
|
2719 } |
|
2720 } |
|
2721 |
|
2722 return true; |
|
2723 } |
|
2724 |
|
2725 function isValid$1() { |
|
2726 return this._isValid; |
|
2727 } |
|
2728 |
|
2729 function createInvalid$1() { |
|
2730 return createDuration(NaN); |
|
2731 } |
|
2732 |
|
2733 function Duration (duration) { |
|
2734 var normalizedInput = normalizeObjectUnits(duration), |
|
2735 years = normalizedInput.year || 0, |
|
2736 quarters = normalizedInput.quarter || 0, |
|
2737 months = normalizedInput.month || 0, |
|
2738 weeks = normalizedInput.week || 0, |
|
2739 days = normalizedInput.day || 0, |
|
2740 hours = normalizedInput.hour || 0, |
|
2741 minutes = normalizedInput.minute || 0, |
|
2742 seconds = normalizedInput.second || 0, |
|
2743 milliseconds = normalizedInput.millisecond || 0; |
|
2744 |
|
2745 this._isValid = isDurationValid(normalizedInput); |
|
2746 |
|
2747 // representation for dateAddRemove |
|
2748 this._milliseconds = +milliseconds + |
|
2749 seconds * 1e3 + // 1000 |
|
2750 minutes * 6e4 + // 1000 * 60 |
|
2751 hours * 1000 * 60 * 60; //using 1000 * 60 * 60 instead of 36e5 to avoid floating point rounding errors https://github.com/moment/moment/issues/2978 |
|
2752 // Because of dateAddRemove treats 24 hours as different from a |
|
2753 // day when working around DST, we need to store them separately |
|
2754 this._days = +days + |
|
2755 weeks * 7; |
|
2756 // It is impossible to translate months into days without knowing |
|
2757 // which months you are are talking about, so we have to store |
|
2758 // it separately. |
|
2759 this._months = +months + |
|
2760 quarters * 3 + |
|
2761 years * 12; |
|
2762 |
|
2763 this._data = {}; |
|
2764 |
|
2765 this._locale = getLocale(); |
|
2766 |
|
2767 this._bubble(); |
|
2768 } |
|
2769 |
|
2770 function isDuration (obj) { |
|
2771 return obj instanceof Duration; |
|
2772 } |
|
2773 |
|
2774 function absRound (number) { |
|
2775 if (number < 0) { |
|
2776 return Math.round(-1 * number) * -1; |
|
2777 } else { |
|
2778 return Math.round(number); |
|
2779 } |
|
2780 } |
|
2781 |
|
2782 // FORMATTING |
|
2783 |
|
2784 function offset (token, separator) { |
|
2785 addFormatToken(token, 0, 0, function () { |
|
2786 var offset = this.utcOffset(); |
|
2787 var sign = '+'; |
|
2788 if (offset < 0) { |
|
2789 offset = -offset; |
|
2790 sign = '-'; |
|
2791 } |
|
2792 return sign + zeroFill(~~(offset / 60), 2) + separator + zeroFill(~~(offset) % 60, 2); |
|
2793 }); |
|
2794 } |
|
2795 |
|
2796 offset('Z', ':'); |
|
2797 offset('ZZ', ''); |
|
2798 |
|
2799 // PARSING |
|
2800 |
|
2801 addRegexToken('Z', matchShortOffset); |
|
2802 addRegexToken('ZZ', matchShortOffset); |
|
2803 addParseToken(['Z', 'ZZ'], function (input, array, config) { |
|
2804 config._useUTC = true; |
|
2805 config._tzm = offsetFromString(matchShortOffset, input); |
|
2806 }); |
|
2807 |
|
2808 // HELPERS |
|
2809 |
|
2810 // timezone chunker |
|
2811 // '+10:00' > ['10', '00'] |
|
2812 // '-1530' > ['-15', '30'] |
|
2813 var chunkOffset = /([\+\-]|\d\d)/gi; |
|
2814 |
|
2815 function offsetFromString(matcher, string) { |
|
2816 var matches = (string || '').match(matcher); |
|
2817 |
|
2818 if (matches === null) { |
|
2819 return null; |
|
2820 } |
|
2821 |
|
2822 var chunk = matches[matches.length - 1] || []; |
|
2823 var parts = (chunk + '').match(chunkOffset) || ['-', 0, 0]; |
|
2824 var minutes = +(parts[1] * 60) + toInt(parts[2]); |
|
2825 |
|
2826 return minutes === 0 ? |
|
2827 0 : |
|
2828 parts[0] === '+' ? minutes : -minutes; |
|
2829 } |
|
2830 |
|
2831 // Return a moment from input, that is local/utc/zone equivalent to model. |
|
2832 function cloneWithOffset(input, model) { |
|
2833 var res, diff; |
|
2834 if (model._isUTC) { |
|
2835 res = model.clone(); |
|
2836 diff = (isMoment(input) || isDate(input) ? input.valueOf() : createLocal(input).valueOf()) - res.valueOf(); |
|
2837 // Use low-level api, because this fn is low-level api. |
|
2838 res._d.setTime(res._d.valueOf() + diff); |
|
2839 hooks.updateOffset(res, false); |
|
2840 return res; |
|
2841 } else { |
|
2842 return createLocal(input).local(); |
|
2843 } |
|
2844 } |
|
2845 |
|
2846 function getDateOffset (m) { |
|
2847 // On Firefox.24 Date#getTimezoneOffset returns a floating point. |
|
2848 // https://github.com/moment/moment/pull/1871 |
|
2849 return -Math.round(m._d.getTimezoneOffset() / 15) * 15; |
|
2850 } |
|
2851 |
|
2852 // HOOKS |
|
2853 |
|
2854 // This function will be called whenever a moment is mutated. |
|
2855 // It is intended to keep the offset in sync with the timezone. |
|
2856 hooks.updateOffset = function () {}; |
|
2857 |
|
2858 // MOMENTS |
|
2859 |
|
2860 // keepLocalTime = true means only change the timezone, without |
|
2861 // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]--> |
|
2862 // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset |
|
2863 // +0200, so we adjust the time as needed, to be valid. |
|
2864 // |
|
2865 // Keeping the time actually adds/subtracts (one hour) |
|
2866 // from the actual represented time. That is why we call updateOffset |
|
2867 // a second time. In case it wants us to change the offset again |
|
2868 // _changeInProgress == true case, then we have to adjust, because |
|
2869 // there is no such time in the given timezone. |
|
2870 function getSetOffset (input, keepLocalTime, keepMinutes) { |
|
2871 var offset = this._offset || 0, |
|
2872 localAdjust; |
|
2873 if (!this.isValid()) { |
|
2874 return input != null ? this : NaN; |
|
2875 } |
|
2876 if (input != null) { |
|
2877 if (typeof input === 'string') { |
|
2878 input = offsetFromString(matchShortOffset, input); |
|
2879 if (input === null) { |
|
2880 return this; |
|
2881 } |
|
2882 } else if (Math.abs(input) < 16 && !keepMinutes) { |
|
2883 input = input * 60; |
|
2884 } |
|
2885 if (!this._isUTC && keepLocalTime) { |
|
2886 localAdjust = getDateOffset(this); |
|
2887 } |
|
2888 this._offset = input; |
|
2889 this._isUTC = true; |
|
2890 if (localAdjust != null) { |
|
2891 this.add(localAdjust, 'm'); |
|
2892 } |
|
2893 if (offset !== input) { |
|
2894 if (!keepLocalTime || this._changeInProgress) { |
|
2895 addSubtract(this, createDuration(input - offset, 'm'), 1, false); |
|
2896 } else if (!this._changeInProgress) { |
|
2897 this._changeInProgress = true; |
|
2898 hooks.updateOffset(this, true); |
|
2899 this._changeInProgress = null; |
|
2900 } |
|
2901 } |
|
2902 return this; |
|
2903 } else { |
|
2904 return this._isUTC ? offset : getDateOffset(this); |
|
2905 } |
|
2906 } |
|
2907 |
|
2908 function getSetZone (input, keepLocalTime) { |
|
2909 if (input != null) { |
|
2910 if (typeof input !== 'string') { |
|
2911 input = -input; |
|
2912 } |
|
2913 |
|
2914 this.utcOffset(input, keepLocalTime); |
|
2915 |
|
2916 return this; |
|
2917 } else { |
|
2918 return -this.utcOffset(); |
|
2919 } |
|
2920 } |
|
2921 |
|
2922 function setOffsetToUTC (keepLocalTime) { |
|
2923 return this.utcOffset(0, keepLocalTime); |
|
2924 } |
|
2925 |
|
2926 function setOffsetToLocal (keepLocalTime) { |
|
2927 if (this._isUTC) { |
|
2928 this.utcOffset(0, keepLocalTime); |
|
2929 this._isUTC = false; |
|
2930 |
|
2931 if (keepLocalTime) { |
|
2932 this.subtract(getDateOffset(this), 'm'); |
|
2933 } |
|
2934 } |
|
2935 return this; |
|
2936 } |
|
2937 |
|
2938 function setOffsetToParsedOffset () { |
|
2939 if (this._tzm != null) { |
|
2940 this.utcOffset(this._tzm, false, true); |
|
2941 } else if (typeof this._i === 'string') { |
|
2942 var tZone = offsetFromString(matchOffset, this._i); |
|
2943 if (tZone != null) { |
|
2944 this.utcOffset(tZone); |
|
2945 } |
|
2946 else { |
|
2947 this.utcOffset(0, true); |
|
2948 } |
|
2949 } |
|
2950 return this; |
|
2951 } |
|
2952 |
|
2953 function hasAlignedHourOffset (input) { |
|
2954 if (!this.isValid()) { |
|
2955 return false; |
|
2956 } |
|
2957 input = input ? createLocal(input).utcOffset() : 0; |
|
2958 |
|
2959 return (this.utcOffset() - input) % 60 === 0; |
|
2960 } |
|
2961 |
|
2962 function isDaylightSavingTime () { |
|
2963 return ( |
|
2964 this.utcOffset() > this.clone().month(0).utcOffset() || |
|
2965 this.utcOffset() > this.clone().month(5).utcOffset() |
|
2966 ); |
|
2967 } |
|
2968 |
|
2969 function isDaylightSavingTimeShifted () { |
|
2970 if (!isUndefined(this._isDSTShifted)) { |
|
2971 return this._isDSTShifted; |
|
2972 } |
|
2973 |
|
2974 var c = {}; |
|
2975 |
|
2976 copyConfig(c, this); |
|
2977 c = prepareConfig(c); |
|
2978 |
|
2979 if (c._a) { |
|
2980 var other = c._isUTC ? createUTC(c._a) : createLocal(c._a); |
|
2981 this._isDSTShifted = this.isValid() && |
|
2982 compareArrays(c._a, other.toArray()) > 0; |
|
2983 } else { |
|
2984 this._isDSTShifted = false; |
|
2985 } |
|
2986 |
|
2987 return this._isDSTShifted; |
|
2988 } |
|
2989 |
|
2990 function isLocal () { |
|
2991 return this.isValid() ? !this._isUTC : false; |
|
2992 } |
|
2993 |
|
2994 function isUtcOffset () { |
|
2995 return this.isValid() ? this._isUTC : false; |
|
2996 } |
|
2997 |
|
2998 function isUtc () { |
|
2999 return this.isValid() ? this._isUTC && this._offset === 0 : false; |
|
3000 } |
|
3001 |
|
3002 // ASP.NET json date format regex |
|
3003 var aspNetRegex = /^(\-|\+)?(?:(\d*)[. ])?(\d+)\:(\d+)(?:\:(\d+)(\.\d*)?)?$/; |
|
3004 |
|
3005 // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html |
|
3006 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere |
|
3007 // and further modified to allow for strings containing both week and day |
|
3008 var isoRegex = /^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/; |
|
3009 |
|
3010 function createDuration (input, key) { |
|
3011 var duration = input, |
|
3012 // matching against regexp is expensive, do it on demand |
|
3013 match = null, |
|
3014 sign, |
|
3015 ret, |
|
3016 diffRes; |
|
3017 |
|
3018 if (isDuration(input)) { |
|
3019 duration = { |
|
3020 ms : input._milliseconds, |
|
3021 d : input._days, |
|
3022 M : input._months |
|
3023 }; |
|
3024 } else if (isNumber(input)) { |
|
3025 duration = {}; |
|
3026 if (key) { |
|
3027 duration[key] = input; |
|
3028 } else { |
|
3029 duration.milliseconds = input; |
|
3030 } |
|
3031 } else if (!!(match = aspNetRegex.exec(input))) { |
|
3032 sign = (match[1] === '-') ? -1 : 1; |
|
3033 duration = { |
|
3034 y : 0, |
|
3035 d : toInt(match[DATE]) * sign, |
|
3036 h : toInt(match[HOUR]) * sign, |
|
3037 m : toInt(match[MINUTE]) * sign, |
|
3038 s : toInt(match[SECOND]) * sign, |
|
3039 ms : toInt(absRound(match[MILLISECOND] * 1000)) * sign // the millisecond decimal point is included in the match |
|
3040 }; |
|
3041 } else if (!!(match = isoRegex.exec(input))) { |
|
3042 sign = (match[1] === '-') ? -1 : (match[1] === '+') ? 1 : 1; |
|
3043 duration = { |
|
3044 y : parseIso(match[2], sign), |
|
3045 M : parseIso(match[3], sign), |
|
3046 w : parseIso(match[4], sign), |
|
3047 d : parseIso(match[5], sign), |
|
3048 h : parseIso(match[6], sign), |
|
3049 m : parseIso(match[7], sign), |
|
3050 s : parseIso(match[8], sign) |
|
3051 }; |
|
3052 } else if (duration == null) {// checks for null or undefined |
|
3053 duration = {}; |
|
3054 } else if (typeof duration === 'object' && ('from' in duration || 'to' in duration)) { |
|
3055 diffRes = momentsDifference(createLocal(duration.from), createLocal(duration.to)); |
|
3056 |
|
3057 duration = {}; |
|
3058 duration.ms = diffRes.milliseconds; |
|
3059 duration.M = diffRes.months; |
|
3060 } |
|
3061 |
|
3062 ret = new Duration(duration); |
|
3063 |
|
3064 if (isDuration(input) && hasOwnProp(input, '_locale')) { |
|
3065 ret._locale = input._locale; |
|
3066 } |
|
3067 |
|
3068 return ret; |
|
3069 } |
|
3070 |
|
3071 createDuration.fn = Duration.prototype; |
|
3072 createDuration.invalid = createInvalid$1; |
|
3073 |
|
3074 function parseIso (inp, sign) { |
|
3075 // We'd normally use ~~inp for this, but unfortunately it also |
|
3076 // converts floats to ints. |
|
3077 // inp may be undefined, so careful calling replace on it. |
|
3078 var res = inp && parseFloat(inp.replace(',', '.')); |
|
3079 // apply sign while we're at it |
|
3080 return (isNaN(res) ? 0 : res) * sign; |
|
3081 } |
|
3082 |
|
3083 function positiveMomentsDifference(base, other) { |
|
3084 var res = {milliseconds: 0, months: 0}; |
|
3085 |
|
3086 res.months = other.month() - base.month() + |
|
3087 (other.year() - base.year()) * 12; |
|
3088 if (base.clone().add(res.months, 'M').isAfter(other)) { |
|
3089 --res.months; |
|
3090 } |
|
3091 |
|
3092 res.milliseconds = +other - +(base.clone().add(res.months, 'M')); |
|
3093 |
|
3094 return res; |
|
3095 } |
|
3096 |
|
3097 function momentsDifference(base, other) { |
|
3098 var res; |
|
3099 if (!(base.isValid() && other.isValid())) { |
|
3100 return {milliseconds: 0, months: 0}; |
|
3101 } |
|
3102 |
|
3103 other = cloneWithOffset(other, base); |
|
3104 if (base.isBefore(other)) { |
|
3105 res = positiveMomentsDifference(base, other); |
|
3106 } else { |
|
3107 res = positiveMomentsDifference(other, base); |
|
3108 res.milliseconds = -res.milliseconds; |
|
3109 res.months = -res.months; |
|
3110 } |
|
3111 |
|
3112 return res; |
|
3113 } |
|
3114 |
|
3115 // TODO: remove 'name' arg after deprecation is removed |
|
3116 function createAdder(direction, name) { |
|
3117 return function (val, period) { |
|
3118 var dur, tmp; |
|
3119 //invert the arguments, but complain about it |
|
3120 if (period !== null && !isNaN(+period)) { |
|
3121 deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period). ' + |
|
3122 'See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info.'); |
|
3123 tmp = val; val = period; period = tmp; |
|
3124 } |
|
3125 |
|
3126 val = typeof val === 'string' ? +val : val; |
|
3127 dur = createDuration(val, period); |
|
3128 addSubtract(this, dur, direction); |
|
3129 return this; |
|
3130 }; |
|
3131 } |
|
3132 |
|
3133 function addSubtract (mom, duration, isAdding, updateOffset) { |
|
3134 var milliseconds = duration._milliseconds, |
|
3135 days = absRound(duration._days), |
|
3136 months = absRound(duration._months); |
|
3137 |
|
3138 if (!mom.isValid()) { |
|
3139 // No op |
|
3140 return; |
|
3141 } |
|
3142 |
|
3143 updateOffset = updateOffset == null ? true : updateOffset; |
|
3144 |
|
3145 if (months) { |
|
3146 setMonth(mom, get(mom, 'Month') + months * isAdding); |
|
3147 } |
|
3148 if (days) { |
|
3149 set$1(mom, 'Date', get(mom, 'Date') + days * isAdding); |
|
3150 } |
|
3151 if (milliseconds) { |
|
3152 mom._d.setTime(mom._d.valueOf() + milliseconds * isAdding); |
|
3153 } |
|
3154 if (updateOffset) { |
|
3155 hooks.updateOffset(mom, days || months); |
|
3156 } |
|
3157 } |
|
3158 |
|
3159 var add = createAdder(1, 'add'); |
|
3160 var subtract = createAdder(-1, 'subtract'); |
|
3161 |
|
3162 function getCalendarFormat(myMoment, now) { |
|
3163 var diff = myMoment.diff(now, 'days', true); |
|
3164 return diff < -6 ? 'sameElse' : |
|
3165 diff < -1 ? 'lastWeek' : |
|
3166 diff < 0 ? 'lastDay' : |
|
3167 diff < 1 ? 'sameDay' : |
|
3168 diff < 2 ? 'nextDay' : |
|
3169 diff < 7 ? 'nextWeek' : 'sameElse'; |
|
3170 } |
|
3171 |
|
3172 function calendar$1 (time, formats) { |
|
3173 // We want to compare the start of today, vs this. |
|
3174 // Getting start-of-today depends on whether we're local/utc/offset or not. |
|
3175 var now = time || createLocal(), |
|
3176 sod = cloneWithOffset(now, this).startOf('day'), |
|
3177 format = hooks.calendarFormat(this, sod) || 'sameElse'; |
|
3178 |
|
3179 var output = formats && (isFunction(formats[format]) ? formats[format].call(this, now) : formats[format]); |
|
3180 |
|
3181 return this.format(output || this.localeData().calendar(format, this, createLocal(now))); |
|
3182 } |
|
3183 |
|
3184 function clone () { |
|
3185 return new Moment(this); |
|
3186 } |
|
3187 |
|
3188 function isAfter (input, units) { |
|
3189 var localInput = isMoment(input) ? input : createLocal(input); |
|
3190 if (!(this.isValid() && localInput.isValid())) { |
|
3191 return false; |
|
3192 } |
|
3193 units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); |
|
3194 if (units === 'millisecond') { |
|
3195 return this.valueOf() > localInput.valueOf(); |
|
3196 } else { |
|
3197 return localInput.valueOf() < this.clone().startOf(units).valueOf(); |
|
3198 } |
|
3199 } |
|
3200 |
|
3201 function isBefore (input, units) { |
|
3202 var localInput = isMoment(input) ? input : createLocal(input); |
|
3203 if (!(this.isValid() && localInput.isValid())) { |
|
3204 return false; |
|
3205 } |
|
3206 units = normalizeUnits(!isUndefined(units) ? units : 'millisecond'); |
|
3207 if (units === 'millisecond') { |
|
3208 return this.valueOf() < localInput.valueOf(); |
|
3209 } else { |
|
3210 return this.clone().endOf(units).valueOf() < localInput.valueOf(); |
|
3211 } |
|
3212 } |
|
3213 |
|
3214 function isBetween (from, to, units, inclusivity) { |
|
3215 inclusivity = inclusivity || '()'; |
|
3216 return (inclusivity[0] === '(' ? this.isAfter(from, units) : !this.isBefore(from, units)) && |
|
3217 (inclusivity[1] === ')' ? this.isBefore(to, units) : !this.isAfter(to, units)); |
|
3218 } |
|
3219 |
|
3220 function isSame (input, units) { |
|
3221 var localInput = isMoment(input) ? input : createLocal(input), |
|
3222 inputMs; |
|
3223 if (!(this.isValid() && localInput.isValid())) { |
|
3224 return false; |
|
3225 } |
|
3226 units = normalizeUnits(units || 'millisecond'); |
|
3227 if (units === 'millisecond') { |
|
3228 return this.valueOf() === localInput.valueOf(); |
|
3229 } else { |
|
3230 inputMs = localInput.valueOf(); |
|
3231 return this.clone().startOf(units).valueOf() <= inputMs && inputMs <= this.clone().endOf(units).valueOf(); |
|
3232 } |
|
3233 } |
|
3234 |
|
3235 function isSameOrAfter (input, units) { |
|
3236 return this.isSame(input, units) || this.isAfter(input,units); |
|
3237 } |
|
3238 |
|
3239 function isSameOrBefore (input, units) { |
|
3240 return this.isSame(input, units) || this.isBefore(input,units); |
|
3241 } |
|
3242 |
|
3243 function diff (input, units, asFloat) { |
|
3244 var that, |
|
3245 zoneDelta, |
|
3246 output; |
|
3247 |
|
3248 if (!this.isValid()) { |
|
3249 return NaN; |
|
3250 } |
|
3251 |
|
3252 that = cloneWithOffset(input, this); |
|
3253 |
|
3254 if (!that.isValid()) { |
|
3255 return NaN; |
|
3256 } |
|
3257 |
|
3258 zoneDelta = (that.utcOffset() - this.utcOffset()) * 6e4; |
|
3259 |
|
3260 units = normalizeUnits(units); |
|
3261 |
|
3262 switch (units) { |
|
3263 case 'year': output = monthDiff(this, that) / 12; break; |
|
3264 case 'month': output = monthDiff(this, that); break; |
|
3265 case 'quarter': output = monthDiff(this, that) / 3; break; |
|
3266 case 'second': output = (this - that) / 1e3; break; // 1000 |
|
3267 case 'minute': output = (this - that) / 6e4; break; // 1000 * 60 |
|
3268 case 'hour': output = (this - that) / 36e5; break; // 1000 * 60 * 60 |
|
3269 case 'day': output = (this - that - zoneDelta) / 864e5; break; // 1000 * 60 * 60 * 24, negate dst |
|
3270 case 'week': output = (this - that - zoneDelta) / 6048e5; break; // 1000 * 60 * 60 * 24 * 7, negate dst |
|
3271 default: output = this - that; |
|
3272 } |
|
3273 |
|
3274 return asFloat ? output : absFloor(output); |
|
3275 } |
|
3276 |
|
3277 function monthDiff (a, b) { |
|
3278 // difference in months |
|
3279 var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()), |
|
3280 // b is in (anchor - 1 month, anchor + 1 month) |
|
3281 anchor = a.clone().add(wholeMonthDiff, 'months'), |
|
3282 anchor2, adjust; |
|
3283 |
|
3284 if (b - anchor < 0) { |
|
3285 anchor2 = a.clone().add(wholeMonthDiff - 1, 'months'); |
|
3286 // linear across the month |
|
3287 adjust = (b - anchor) / (anchor - anchor2); |
|
3288 } else { |
|
3289 anchor2 = a.clone().add(wholeMonthDiff + 1, 'months'); |
|
3290 // linear across the month |
|
3291 adjust = (b - anchor) / (anchor2 - anchor); |
|
3292 } |
|
3293 |
|
3294 //check for negative zero, return zero if negative zero |
|
3295 return -(wholeMonthDiff + adjust) || 0; |
|
3296 } |
|
3297 |
|
3298 hooks.defaultFormat = 'YYYY-MM-DDTHH:mm:ssZ'; |
|
3299 hooks.defaultFormatUtc = 'YYYY-MM-DDTHH:mm:ss[Z]'; |
|
3300 |
|
3301 function toString () { |
|
3302 return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ'); |
|
3303 } |
|
3304 |
|
3305 function toISOString(keepOffset) { |
|
3306 if (!this.isValid()) { |
|
3307 return null; |
|
3308 } |
|
3309 var utc = keepOffset !== true; |
|
3310 var m = utc ? this.clone().utc() : this; |
|
3311 if (m.year() < 0 || m.year() > 9999) { |
|
3312 return formatMoment(m, utc ? 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYYYY-MM-DD[T]HH:mm:ss.SSSZ'); |
|
3313 } |
|
3314 if (isFunction(Date.prototype.toISOString)) { |
|
3315 // native implementation is ~50x faster, use it when we can |
|
3316 if (utc) { |
|
3317 return this.toDate().toISOString(); |
|
3318 } else { |
|
3319 return new Date(this.valueOf() + this.utcOffset() * 60 * 1000).toISOString().replace('Z', formatMoment(m, 'Z')); |
|
3320 } |
|
3321 } |
|
3322 return formatMoment(m, utc ? 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]' : 'YYYY-MM-DD[T]HH:mm:ss.SSSZ'); |
|
3323 } |
|
3324 |
|
3325 /** |
|
3326 * Return a human readable representation of a moment that can |
|
3327 * also be evaluated to get a new moment which is the same |
|
3328 * |
|
3329 * @link https://nodejs.org/dist/latest/docs/api/util.html#util_custom_inspect_function_on_objects |
|
3330 */ |
|
3331 function inspect () { |
|
3332 if (!this.isValid()) { |
|
3333 return 'moment.invalid(/* ' + this._i + ' */)'; |
|
3334 } |
|
3335 var func = 'moment'; |
|
3336 var zone = ''; |
|
3337 if (!this.isLocal()) { |
|
3338 func = this.utcOffset() === 0 ? 'moment.utc' : 'moment.parseZone'; |
|
3339 zone = 'Z'; |
|
3340 } |
|
3341 var prefix = '[' + func + '("]'; |
|
3342 var year = (0 <= this.year() && this.year() <= 9999) ? 'YYYY' : 'YYYYYY'; |
|
3343 var datetime = '-MM-DD[T]HH:mm:ss.SSS'; |
|
3344 var suffix = zone + '[")]'; |
|
3345 |
|
3346 return this.format(prefix + year + datetime + suffix); |
|
3347 } |
|
3348 |
|
3349 function format (inputString) { |
|
3350 if (!inputString) { |
|
3351 inputString = this.isUtc() ? hooks.defaultFormatUtc : hooks.defaultFormat; |
|
3352 } |
|
3353 var output = formatMoment(this, inputString); |
|
3354 return this.localeData().postformat(output); |
|
3355 } |
|
3356 |
|
3357 function from (time, withoutSuffix) { |
|
3358 if (this.isValid() && |
|
3359 ((isMoment(time) && time.isValid()) || |
|
3360 createLocal(time).isValid())) { |
|
3361 return createDuration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix); |
|
3362 } else { |
|
3363 return this.localeData().invalidDate(); |
|
3364 } |
|
3365 } |
|
3366 |
|
3367 function fromNow (withoutSuffix) { |
|
3368 return this.from(createLocal(), withoutSuffix); |
|
3369 } |
|
3370 |
|
3371 function to (time, withoutSuffix) { |
|
3372 if (this.isValid() && |
|
3373 ((isMoment(time) && time.isValid()) || |
|
3374 createLocal(time).isValid())) { |
|
3375 return createDuration({from: this, to: time}).locale(this.locale()).humanize(!withoutSuffix); |
|
3376 } else { |
|
3377 return this.localeData().invalidDate(); |
|
3378 } |
|
3379 } |
|
3380 |
|
3381 function toNow (withoutSuffix) { |
|
3382 return this.to(createLocal(), withoutSuffix); |
|
3383 } |
|
3384 |
|
3385 // If passed a locale key, it will set the locale for this |
|
3386 // instance. Otherwise, it will return the locale configuration |
|
3387 // variables for this instance. |
|
3388 function locale (key) { |
|
3389 var newLocaleData; |
|
3390 |
|
3391 if (key === undefined) { |
|
3392 return this._locale._abbr; |
|
3393 } else { |
|
3394 newLocaleData = getLocale(key); |
|
3395 if (newLocaleData != null) { |
|
3396 this._locale = newLocaleData; |
|
3397 } |
|
3398 return this; |
|
3399 } |
|
3400 } |
|
3401 |
|
3402 var lang = deprecate( |
|
3403 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.', |
|
3404 function (key) { |
|
3405 if (key === undefined) { |
|
3406 return this.localeData(); |
|
3407 } else { |
|
3408 return this.locale(key); |
|
3409 } |
|
3410 } |
|
3411 ); |
|
3412 |
|
3413 function localeData () { |
|
3414 return this._locale; |
|
3415 } |
|
3416 |
|
3417 function startOf (units) { |
|
3418 units = normalizeUnits(units); |
|
3419 // the following switch intentionally omits break keywords |
|
3420 // to utilize falling through the cases. |
|
3421 switch (units) { |
|
3422 case 'year': |
|
3423 this.month(0); |
|
3424 /* falls through */ |
|
3425 case 'quarter': |
|
3426 case 'month': |
|
3427 this.date(1); |
|
3428 /* falls through */ |
|
3429 case 'week': |
|
3430 case 'isoWeek': |
|
3431 case 'day': |
|
3432 case 'date': |
|
3433 this.hours(0); |
|
3434 /* falls through */ |
|
3435 case 'hour': |
|
3436 this.minutes(0); |
|
3437 /* falls through */ |
|
3438 case 'minute': |
|
3439 this.seconds(0); |
|
3440 /* falls through */ |
|
3441 case 'second': |
|
3442 this.milliseconds(0); |
|
3443 } |
|
3444 |
|
3445 // weeks are a special case |
|
3446 if (units === 'week') { |
|
3447 this.weekday(0); |
|
3448 } |
|
3449 if (units === 'isoWeek') { |
|
3450 this.isoWeekday(1); |
|
3451 } |
|
3452 |
|
3453 // quarters are also special |
|
3454 if (units === 'quarter') { |
|
3455 this.month(Math.floor(this.month() / 3) * 3); |
|
3456 } |
|
3457 |
|
3458 return this; |
|
3459 } |
|
3460 |
|
3461 function endOf (units) { |
|
3462 units = normalizeUnits(units); |
|
3463 if (units === undefined || units === 'millisecond') { |
|
3464 return this; |
|
3465 } |
|
3466 |
|
3467 // 'date' is an alias for 'day', so it should be considered as such. |
|
3468 if (units === 'date') { |
|
3469 units = 'day'; |
|
3470 } |
|
3471 |
|
3472 return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms'); |
|
3473 } |
|
3474 |
|
3475 function valueOf () { |
|
3476 return this._d.valueOf() - ((this._offset || 0) * 60000); |
|
3477 } |
|
3478 |
|
3479 function unix () { |
|
3480 return Math.floor(this.valueOf() / 1000); |
|
3481 } |
|
3482 |
|
3483 function toDate () { |
|
3484 return new Date(this.valueOf()); |
|
3485 } |
|
3486 |
|
3487 function toArray () { |
|
3488 var m = this; |
|
3489 return [m.year(), m.month(), m.date(), m.hour(), m.minute(), m.second(), m.millisecond()]; |
|
3490 } |
|
3491 |
|
3492 function toObject () { |
|
3493 var m = this; |
|
3494 return { |
|
3495 years: m.year(), |
|
3496 months: m.month(), |
|
3497 date: m.date(), |
|
3498 hours: m.hours(), |
|
3499 minutes: m.minutes(), |
|
3500 seconds: m.seconds(), |
|
3501 milliseconds: m.milliseconds() |
|
3502 }; |
|
3503 } |
|
3504 |
|
3505 function toJSON () { |
|
3506 // new Date(NaN).toJSON() === null |
|
3507 return this.isValid() ? this.toISOString() : null; |
|
3508 } |
|
3509 |
|
3510 function isValid$2 () { |
|
3511 return isValid(this); |
|
3512 } |
|
3513 |
|
3514 function parsingFlags () { |
|
3515 return extend({}, getParsingFlags(this)); |
|
3516 } |
|
3517 |
|
3518 function invalidAt () { |
|
3519 return getParsingFlags(this).overflow; |
|
3520 } |
|
3521 |
|
3522 function creationData() { |
|
3523 return { |
|
3524 input: this._i, |
|
3525 format: this._f, |
|
3526 locale: this._locale, |
|
3527 isUTC: this._isUTC, |
|
3528 strict: this._strict |
|
3529 }; |
|
3530 } |
|
3531 |
|
3532 // FORMATTING |
|
3533 |
|
3534 addFormatToken(0, ['gg', 2], 0, function () { |
|
3535 return this.weekYear() % 100; |
|
3536 }); |
|
3537 |
|
3538 addFormatToken(0, ['GG', 2], 0, function () { |
|
3539 return this.isoWeekYear() % 100; |
|
3540 }); |
|
3541 |
|
3542 function addWeekYearFormatToken (token, getter) { |
|
3543 addFormatToken(0, [token, token.length], 0, getter); |
|
3544 } |
|
3545 |
|
3546 addWeekYearFormatToken('gggg', 'weekYear'); |
|
3547 addWeekYearFormatToken('ggggg', 'weekYear'); |
|
3548 addWeekYearFormatToken('GGGG', 'isoWeekYear'); |
|
3549 addWeekYearFormatToken('GGGGG', 'isoWeekYear'); |
|
3550 |
|
3551 // ALIASES |
|
3552 |
|
3553 addUnitAlias('weekYear', 'gg'); |
|
3554 addUnitAlias('isoWeekYear', 'GG'); |
|
3555 |
|
3556 // PRIORITY |
|
3557 |
|
3558 addUnitPriority('weekYear', 1); |
|
3559 addUnitPriority('isoWeekYear', 1); |
|
3560 |
|
3561 |
|
3562 // PARSING |
|
3563 |
|
3564 addRegexToken('G', matchSigned); |
|
3565 addRegexToken('g', matchSigned); |
|
3566 addRegexToken('GG', match1to2, match2); |
|
3567 addRegexToken('gg', match1to2, match2); |
|
3568 addRegexToken('GGGG', match1to4, match4); |
|
3569 addRegexToken('gggg', match1to4, match4); |
|
3570 addRegexToken('GGGGG', match1to6, match6); |
|
3571 addRegexToken('ggggg', match1to6, match6); |
|
3572 |
|
3573 addWeekParseToken(['gggg', 'ggggg', 'GGGG', 'GGGGG'], function (input, week, config, token) { |
|
3574 week[token.substr(0, 2)] = toInt(input); |
|
3575 }); |
|
3576 |
|
3577 addWeekParseToken(['gg', 'GG'], function (input, week, config, token) { |
|
3578 week[token] = hooks.parseTwoDigitYear(input); |
|
3579 }); |
|
3580 |
|
3581 // MOMENTS |
|
3582 |
|
3583 function getSetWeekYear (input) { |
|
3584 return getSetWeekYearHelper.call(this, |
|
3585 input, |
|
3586 this.week(), |
|
3587 this.weekday(), |
|
3588 this.localeData()._week.dow, |
|
3589 this.localeData()._week.doy); |
|
3590 } |
|
3591 |
|
3592 function getSetISOWeekYear (input) { |
|
3593 return getSetWeekYearHelper.call(this, |
|
3594 input, this.isoWeek(), this.isoWeekday(), 1, 4); |
|
3595 } |
|
3596 |
|
3597 function getISOWeeksInYear () { |
|
3598 return weeksInYear(this.year(), 1, 4); |
|
3599 } |
|
3600 |
|
3601 function getWeeksInYear () { |
|
3602 var weekInfo = this.localeData()._week; |
|
3603 return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy); |
|
3604 } |
|
3605 |
|
3606 function getSetWeekYearHelper(input, week, weekday, dow, doy) { |
|
3607 var weeksTarget; |
|
3608 if (input == null) { |
|
3609 return weekOfYear(this, dow, doy).year; |
|
3610 } else { |
|
3611 weeksTarget = weeksInYear(input, dow, doy); |
|
3612 if (week > weeksTarget) { |
|
3613 week = weeksTarget; |
|
3614 } |
|
3615 return setWeekAll.call(this, input, week, weekday, dow, doy); |
|
3616 } |
|
3617 } |
|
3618 |
|
3619 function setWeekAll(weekYear, week, weekday, dow, doy) { |
|
3620 var dayOfYearData = dayOfYearFromWeeks(weekYear, week, weekday, dow, doy), |
|
3621 date = createUTCDate(dayOfYearData.year, 0, dayOfYearData.dayOfYear); |
|
3622 |
|
3623 this.year(date.getUTCFullYear()); |
|
3624 this.month(date.getUTCMonth()); |
|
3625 this.date(date.getUTCDate()); |
|
3626 return this; |
|
3627 } |
|
3628 |
|
3629 // FORMATTING |
|
3630 |
|
3631 addFormatToken('Q', 0, 'Qo', 'quarter'); |
|
3632 |
|
3633 // ALIASES |
|
3634 |
|
3635 addUnitAlias('quarter', 'Q'); |
|
3636 |
|
3637 // PRIORITY |
|
3638 |
|
3639 addUnitPriority('quarter', 7); |
|
3640 |
|
3641 // PARSING |
|
3642 |
|
3643 addRegexToken('Q', match1); |
|
3644 addParseToken('Q', function (input, array) { |
|
3645 array[MONTH] = (toInt(input) - 1) * 3; |
|
3646 }); |
|
3647 |
|
3648 // MOMENTS |
|
3649 |
|
3650 function getSetQuarter (input) { |
|
3651 return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3); |
|
3652 } |
|
3653 |
|
3654 // FORMATTING |
|
3655 |
|
3656 addFormatToken('D', ['DD', 2], 'Do', 'date'); |
|
3657 |
|
3658 // ALIASES |
|
3659 |
|
3660 addUnitAlias('date', 'D'); |
|
3661 |
|
3662 // PRIORITY |
|
3663 addUnitPriority('date', 9); |
|
3664 |
|
3665 // PARSING |
|
3666 |
|
3667 addRegexToken('D', match1to2); |
|
3668 addRegexToken('DD', match1to2, match2); |
|
3669 addRegexToken('Do', function (isStrict, locale) { |
|
3670 // TODO: Remove "ordinalParse" fallback in next major release. |
|
3671 return isStrict ? |
|
3672 (locale._dayOfMonthOrdinalParse || locale._ordinalParse) : |
|
3673 locale._dayOfMonthOrdinalParseLenient; |
|
3674 }); |
|
3675 |
|
3676 addParseToken(['D', 'DD'], DATE); |
|
3677 addParseToken('Do', function (input, array) { |
|
3678 array[DATE] = toInt(input.match(match1to2)[0]); |
|
3679 }); |
|
3680 |
|
3681 // MOMENTS |
|
3682 |
|
3683 var getSetDayOfMonth = makeGetSet('Date', true); |
|
3684 |
|
3685 // FORMATTING |
|
3686 |
|
3687 addFormatToken('DDD', ['DDDD', 3], 'DDDo', 'dayOfYear'); |
|
3688 |
|
3689 // ALIASES |
|
3690 |
|
3691 addUnitAlias('dayOfYear', 'DDD'); |
|
3692 |
|
3693 // PRIORITY |
|
3694 addUnitPriority('dayOfYear', 4); |
|
3695 |
|
3696 // PARSING |
|
3697 |
|
3698 addRegexToken('DDD', match1to3); |
|
3699 addRegexToken('DDDD', match3); |
|
3700 addParseToken(['DDD', 'DDDD'], function (input, array, config) { |
|
3701 config._dayOfYear = toInt(input); |
|
3702 }); |
|
3703 |
|
3704 // HELPERS |
|
3705 |
|
3706 // MOMENTS |
|
3707 |
|
3708 function getSetDayOfYear (input) { |
|
3709 var dayOfYear = Math.round((this.clone().startOf('day') - this.clone().startOf('year')) / 864e5) + 1; |
|
3710 return input == null ? dayOfYear : this.add((input - dayOfYear), 'd'); |
|
3711 } |
|
3712 |
|
3713 // FORMATTING |
|
3714 |
|
3715 addFormatToken('m', ['mm', 2], 0, 'minute'); |
|
3716 |
|
3717 // ALIASES |
|
3718 |
|
3719 addUnitAlias('minute', 'm'); |
|
3720 |
|
3721 // PRIORITY |
|
3722 |
|
3723 addUnitPriority('minute', 14); |
|
3724 |
|
3725 // PARSING |
|
3726 |
|
3727 addRegexToken('m', match1to2); |
|
3728 addRegexToken('mm', match1to2, match2); |
|
3729 addParseToken(['m', 'mm'], MINUTE); |
|
3730 |
|
3731 // MOMENTS |
|
3732 |
|
3733 var getSetMinute = makeGetSet('Minutes', false); |
|
3734 |
|
3735 // FORMATTING |
|
3736 |
|
3737 addFormatToken('s', ['ss', 2], 0, 'second'); |
|
3738 |
|
3739 // ALIASES |
|
3740 |
|
3741 addUnitAlias('second', 's'); |
|
3742 |
|
3743 // PRIORITY |
|
3744 |
|
3745 addUnitPriority('second', 15); |
|
3746 |
|
3747 // PARSING |
|
3748 |
|
3749 addRegexToken('s', match1to2); |
|
3750 addRegexToken('ss', match1to2, match2); |
|
3751 addParseToken(['s', 'ss'], SECOND); |
|
3752 |
|
3753 // MOMENTS |
|
3754 |
|
3755 var getSetSecond = makeGetSet('Seconds', false); |
|
3756 |
|
3757 // FORMATTING |
|
3758 |
|
3759 addFormatToken('S', 0, 0, function () { |
|
3760 return ~~(this.millisecond() / 100); |
|
3761 }); |
|
3762 |
|
3763 addFormatToken(0, ['SS', 2], 0, function () { |
|
3764 return ~~(this.millisecond() / 10); |
|
3765 }); |
|
3766 |
|
3767 addFormatToken(0, ['SSS', 3], 0, 'millisecond'); |
|
3768 addFormatToken(0, ['SSSS', 4], 0, function () { |
|
3769 return this.millisecond() * 10; |
|
3770 }); |
|
3771 addFormatToken(0, ['SSSSS', 5], 0, function () { |
|
3772 return this.millisecond() * 100; |
|
3773 }); |
|
3774 addFormatToken(0, ['SSSSSS', 6], 0, function () { |
|
3775 return this.millisecond() * 1000; |
|
3776 }); |
|
3777 addFormatToken(0, ['SSSSSSS', 7], 0, function () { |
|
3778 return this.millisecond() * 10000; |
|
3779 }); |
|
3780 addFormatToken(0, ['SSSSSSSS', 8], 0, function () { |
|
3781 return this.millisecond() * 100000; |
|
3782 }); |
|
3783 addFormatToken(0, ['SSSSSSSSS', 9], 0, function () { |
|
3784 return this.millisecond() * 1000000; |
|
3785 }); |
|
3786 |
|
3787 |
|
3788 // ALIASES |
|
3789 |
|
3790 addUnitAlias('millisecond', 'ms'); |
|
3791 |
|
3792 // PRIORITY |
|
3793 |
|
3794 addUnitPriority('millisecond', 16); |
|
3795 |
|
3796 // PARSING |
|
3797 |
|
3798 addRegexToken('S', match1to3, match1); |
|
3799 addRegexToken('SS', match1to3, match2); |
|
3800 addRegexToken('SSS', match1to3, match3); |
|
3801 |
|
3802 var token; |
|
3803 for (token = 'SSSS'; token.length <= 9; token += 'S') { |
|
3804 addRegexToken(token, matchUnsigned); |
|
3805 } |
|
3806 |
|
3807 function parseMs(input, array) { |
|
3808 array[MILLISECOND] = toInt(('0.' + input) * 1000); |
|
3809 } |
|
3810 |
|
3811 for (token = 'S'; token.length <= 9; token += 'S') { |
|
3812 addParseToken(token, parseMs); |
|
3813 } |
|
3814 // MOMENTS |
|
3815 |
|
3816 var getSetMillisecond = makeGetSet('Milliseconds', false); |
|
3817 |
|
3818 // FORMATTING |
|
3819 |
|
3820 addFormatToken('z', 0, 0, 'zoneAbbr'); |
|
3821 addFormatToken('zz', 0, 0, 'zoneName'); |
|
3822 |
|
3823 // MOMENTS |
|
3824 |
|
3825 function getZoneAbbr () { |
|
3826 return this._isUTC ? 'UTC' : ''; |
|
3827 } |
|
3828 |
|
3829 function getZoneName () { |
|
3830 return this._isUTC ? 'Coordinated Universal Time' : ''; |
|
3831 } |
|
3832 |
|
3833 var proto = Moment.prototype; |
|
3834 |
|
3835 proto.add = add; |
|
3836 proto.calendar = calendar$1; |
|
3837 proto.clone = clone; |
|
3838 proto.diff = diff; |
|
3839 proto.endOf = endOf; |
|
3840 proto.format = format; |
|
3841 proto.from = from; |
|
3842 proto.fromNow = fromNow; |
|
3843 proto.to = to; |
|
3844 proto.toNow = toNow; |
|
3845 proto.get = stringGet; |
|
3846 proto.invalidAt = invalidAt; |
|
3847 proto.isAfter = isAfter; |
|
3848 proto.isBefore = isBefore; |
|
3849 proto.isBetween = isBetween; |
|
3850 proto.isSame = isSame; |
|
3851 proto.isSameOrAfter = isSameOrAfter; |
|
3852 proto.isSameOrBefore = isSameOrBefore; |
|
3853 proto.isValid = isValid$2; |
|
3854 proto.lang = lang; |
|
3855 proto.locale = locale; |
|
3856 proto.localeData = localeData; |
|
3857 proto.max = prototypeMax; |
|
3858 proto.min = prototypeMin; |
|
3859 proto.parsingFlags = parsingFlags; |
|
3860 proto.set = stringSet; |
|
3861 proto.startOf = startOf; |
|
3862 proto.subtract = subtract; |
|
3863 proto.toArray = toArray; |
|
3864 proto.toObject = toObject; |
|
3865 proto.toDate = toDate; |
|
3866 proto.toISOString = toISOString; |
|
3867 proto.inspect = inspect; |
|
3868 proto.toJSON = toJSON; |
|
3869 proto.toString = toString; |
|
3870 proto.unix = unix; |
|
3871 proto.valueOf = valueOf; |
|
3872 proto.creationData = creationData; |
|
3873 proto.year = getSetYear; |
|
3874 proto.isLeapYear = getIsLeapYear; |
|
3875 proto.weekYear = getSetWeekYear; |
|
3876 proto.isoWeekYear = getSetISOWeekYear; |
|
3877 proto.quarter = proto.quarters = getSetQuarter; |
|
3878 proto.month = getSetMonth; |
|
3879 proto.daysInMonth = getDaysInMonth; |
|
3880 proto.week = proto.weeks = getSetWeek; |
|
3881 proto.isoWeek = proto.isoWeeks = getSetISOWeek; |
|
3882 proto.weeksInYear = getWeeksInYear; |
|
3883 proto.isoWeeksInYear = getISOWeeksInYear; |
|
3884 proto.date = getSetDayOfMonth; |
|
3885 proto.day = proto.days = getSetDayOfWeek; |
|
3886 proto.weekday = getSetLocaleDayOfWeek; |
|
3887 proto.isoWeekday = getSetISODayOfWeek; |
|
3888 proto.dayOfYear = getSetDayOfYear; |
|
3889 proto.hour = proto.hours = getSetHour; |
|
3890 proto.minute = proto.minutes = getSetMinute; |
|
3891 proto.second = proto.seconds = getSetSecond; |
|
3892 proto.millisecond = proto.milliseconds = getSetMillisecond; |
|
3893 proto.utcOffset = getSetOffset; |
|
3894 proto.utc = setOffsetToUTC; |
|
3895 proto.local = setOffsetToLocal; |
|
3896 proto.parseZone = setOffsetToParsedOffset; |
|
3897 proto.hasAlignedHourOffset = hasAlignedHourOffset; |
|
3898 proto.isDST = isDaylightSavingTime; |
|
3899 proto.isLocal = isLocal; |
|
3900 proto.isUtcOffset = isUtcOffset; |
|
3901 proto.isUtc = isUtc; |
|
3902 proto.isUTC = isUtc; |
|
3903 proto.zoneAbbr = getZoneAbbr; |
|
3904 proto.zoneName = getZoneName; |
|
3905 proto.dates = deprecate('dates accessor is deprecated. Use date instead.', getSetDayOfMonth); |
|
3906 proto.months = deprecate('months accessor is deprecated. Use month instead', getSetMonth); |
|
3907 proto.years = deprecate('years accessor is deprecated. Use year instead', getSetYear); |
|
3908 proto.zone = deprecate('moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/', getSetZone); |
|
3909 proto.isDSTShifted = deprecate('isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information', isDaylightSavingTimeShifted); |
|
3910 |
|
3911 function createUnix (input) { |
|
3912 return createLocal(input * 1000); |
|
3913 } |
|
3914 |
|
3915 function createInZone () { |
|
3916 return createLocal.apply(null, arguments).parseZone(); |
|
3917 } |
|
3918 |
|
3919 function preParsePostFormat (string) { |
|
3920 return string; |
|
3921 } |
|
3922 |
|
3923 var proto$1 = Locale.prototype; |
|
3924 |
|
3925 proto$1.calendar = calendar; |
|
3926 proto$1.longDateFormat = longDateFormat; |
|
3927 proto$1.invalidDate = invalidDate; |
|
3928 proto$1.ordinal = ordinal; |
|
3929 proto$1.preparse = preParsePostFormat; |
|
3930 proto$1.postformat = preParsePostFormat; |
|
3931 proto$1.relativeTime = relativeTime; |
|
3932 proto$1.pastFuture = pastFuture; |
|
3933 proto$1.set = set; |
|
3934 |
|
3935 proto$1.months = localeMonths; |
|
3936 proto$1.monthsShort = localeMonthsShort; |
|
3937 proto$1.monthsParse = localeMonthsParse; |
|
3938 proto$1.monthsRegex = monthsRegex; |
|
3939 proto$1.monthsShortRegex = monthsShortRegex; |
|
3940 proto$1.week = localeWeek; |
|
3941 proto$1.firstDayOfYear = localeFirstDayOfYear; |
|
3942 proto$1.firstDayOfWeek = localeFirstDayOfWeek; |
|
3943 |
|
3944 proto$1.weekdays = localeWeekdays; |
|
3945 proto$1.weekdaysMin = localeWeekdaysMin; |
|
3946 proto$1.weekdaysShort = localeWeekdaysShort; |
|
3947 proto$1.weekdaysParse = localeWeekdaysParse; |
|
3948 |
|
3949 proto$1.weekdaysRegex = weekdaysRegex; |
|
3950 proto$1.weekdaysShortRegex = weekdaysShortRegex; |
|
3951 proto$1.weekdaysMinRegex = weekdaysMinRegex; |
|
3952 |
|
3953 proto$1.isPM = localeIsPM; |
|
3954 proto$1.meridiem = localeMeridiem; |
|
3955 |
|
3956 function get$1 (format, index, field, setter) { |
|
3957 var locale = getLocale(); |
|
3958 var utc = createUTC().set(setter, index); |
|
3959 return locale[field](utc, format); |
|
3960 } |
|
3961 |
|
3962 function listMonthsImpl (format, index, field) { |
|
3963 if (isNumber(format)) { |
|
3964 index = format; |
|
3965 format = undefined; |
|
3966 } |
|
3967 |
|
3968 format = format || ''; |
|
3969 |
|
3970 if (index != null) { |
|
3971 return get$1(format, index, field, 'month'); |
|
3972 } |
|
3973 |
|
3974 var i; |
|
3975 var out = []; |
|
3976 for (i = 0; i < 12; i++) { |
|
3977 out[i] = get$1(format, i, field, 'month'); |
|
3978 } |
|
3979 return out; |
|
3980 } |
|
3981 |
|
3982 // () |
|
3983 // (5) |
|
3984 // (fmt, 5) |
|
3985 // (fmt) |
|
3986 // (true) |
|
3987 // (true, 5) |
|
3988 // (true, fmt, 5) |
|
3989 // (true, fmt) |
|
3990 function listWeekdaysImpl (localeSorted, format, index, field) { |
|
3991 if (typeof localeSorted === 'boolean') { |
|
3992 if (isNumber(format)) { |
|
3993 index = format; |
|
3994 format = undefined; |
|
3995 } |
|
3996 |
|
3997 format = format || ''; |
|
3998 } else { |
|
3999 format = localeSorted; |
|
4000 index = format; |
|
4001 localeSorted = false; |
|
4002 |
|
4003 if (isNumber(format)) { |
|
4004 index = format; |
|
4005 format = undefined; |
|
4006 } |
|
4007 |
|
4008 format = format || ''; |
|
4009 } |
|
4010 |
|
4011 var locale = getLocale(), |
|
4012 shift = localeSorted ? locale._week.dow : 0; |
|
4013 |
|
4014 if (index != null) { |
|
4015 return get$1(format, (index + shift) % 7, field, 'day'); |
|
4016 } |
|
4017 |
|
4018 var i; |
|
4019 var out = []; |
|
4020 for (i = 0; i < 7; i++) { |
|
4021 out[i] = get$1(format, (i + shift) % 7, field, 'day'); |
|
4022 } |
|
4023 return out; |
|
4024 } |
|
4025 |
|
4026 function listMonths (format, index) { |
|
4027 return listMonthsImpl(format, index, 'months'); |
|
4028 } |
|
4029 |
|
4030 function listMonthsShort (format, index) { |
|
4031 return listMonthsImpl(format, index, 'monthsShort'); |
|
4032 } |
|
4033 |
|
4034 function listWeekdays (localeSorted, format, index) { |
|
4035 return listWeekdaysImpl(localeSorted, format, index, 'weekdays'); |
|
4036 } |
|
4037 |
|
4038 function listWeekdaysShort (localeSorted, format, index) { |
|
4039 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysShort'); |
|
4040 } |
|
4041 |
|
4042 function listWeekdaysMin (localeSorted, format, index) { |
|
4043 return listWeekdaysImpl(localeSorted, format, index, 'weekdaysMin'); |
|
4044 } |
|
4045 |
|
4046 getSetGlobalLocale('en', { |
|
4047 dayOfMonthOrdinalParse: /\d{1,2}(th|st|nd|rd)/, |
|
4048 ordinal : function (number) { |
|
4049 var b = number % 10, |
|
4050 output = (toInt(number % 100 / 10) === 1) ? 'th' : |
|
4051 (b === 1) ? 'st' : |
|
4052 (b === 2) ? 'nd' : |
|
4053 (b === 3) ? 'rd' : 'th'; |
|
4054 return number + output; |
|
4055 } |
|
4056 }); |
|
4057 |
|
4058 // Side effect imports |
|
4059 |
|
4060 hooks.lang = deprecate('moment.lang is deprecated. Use moment.locale instead.', getSetGlobalLocale); |
|
4061 hooks.langData = deprecate('moment.langData is deprecated. Use moment.localeData instead.', getLocale); |
|
4062 |
|
4063 var mathAbs = Math.abs; |
|
4064 |
|
4065 function abs () { |
|
4066 var data = this._data; |
|
4067 |
|
4068 this._milliseconds = mathAbs(this._milliseconds); |
|
4069 this._days = mathAbs(this._days); |
|
4070 this._months = mathAbs(this._months); |
|
4071 |
|
4072 data.milliseconds = mathAbs(data.milliseconds); |
|
4073 data.seconds = mathAbs(data.seconds); |
|
4074 data.minutes = mathAbs(data.minutes); |
|
4075 data.hours = mathAbs(data.hours); |
|
4076 data.months = mathAbs(data.months); |
|
4077 data.years = mathAbs(data.years); |
|
4078 |
|
4079 return this; |
|
4080 } |
|
4081 |
|
4082 function addSubtract$1 (duration, input, value, direction) { |
|
4083 var other = createDuration(input, value); |
|
4084 |
|
4085 duration._milliseconds += direction * other._milliseconds; |
|
4086 duration._days += direction * other._days; |
|
4087 duration._months += direction * other._months; |
|
4088 |
|
4089 return duration._bubble(); |
|
4090 } |
|
4091 |
|
4092 // supports only 2.0-style add(1, 's') or add(duration) |
|
4093 function add$1 (input, value) { |
|
4094 return addSubtract$1(this, input, value, 1); |
|
4095 } |
|
4096 |
|
4097 // supports only 2.0-style subtract(1, 's') or subtract(duration) |
|
4098 function subtract$1 (input, value) { |
|
4099 return addSubtract$1(this, input, value, -1); |
|
4100 } |
|
4101 |
|
4102 function absCeil (number) { |
|
4103 if (number < 0) { |
|
4104 return Math.floor(number); |
|
4105 } else { |
|
4106 return Math.ceil(number); |
|
4107 } |
|
4108 } |
|
4109 |
|
4110 function bubble () { |
|
4111 var milliseconds = this._milliseconds; |
|
4112 var days = this._days; |
|
4113 var months = this._months; |
|
4114 var data = this._data; |
|
4115 var seconds, minutes, hours, years, monthsFromDays; |
|
4116 |
|
4117 // if we have a mix of positive and negative values, bubble down first |
|
4118 // check: https://github.com/moment/moment/issues/2166 |
|
4119 if (!((milliseconds >= 0 && days >= 0 && months >= 0) || |
|
4120 (milliseconds <= 0 && days <= 0 && months <= 0))) { |
|
4121 milliseconds += absCeil(monthsToDays(months) + days) * 864e5; |
|
4122 days = 0; |
|
4123 months = 0; |
|
4124 } |
|
4125 |
|
4126 // The following code bubbles up values, see the tests for |
|
4127 // examples of what that means. |
|
4128 data.milliseconds = milliseconds % 1000; |
|
4129 |
|
4130 seconds = absFloor(milliseconds / 1000); |
|
4131 data.seconds = seconds % 60; |
|
4132 |
|
4133 minutes = absFloor(seconds / 60); |
|
4134 data.minutes = minutes % 60; |
|
4135 |
|
4136 hours = absFloor(minutes / 60); |
|
4137 data.hours = hours % 24; |
|
4138 |
|
4139 days += absFloor(hours / 24); |
|
4140 |
|
4141 // convert days to months |
|
4142 monthsFromDays = absFloor(daysToMonths(days)); |
|
4143 months += monthsFromDays; |
|
4144 days -= absCeil(monthsToDays(monthsFromDays)); |
|
4145 |
|
4146 // 12 months -> 1 year |
|
4147 years = absFloor(months / 12); |
|
4148 months %= 12; |
|
4149 |
|
4150 data.days = days; |
|
4151 data.months = months; |
|
4152 data.years = years; |
|
4153 |
|
4154 return this; |
|
4155 } |
|
4156 |
|
4157 function daysToMonths (days) { |
|
4158 // 400 years have 146097 days (taking into account leap year rules) |
|
4159 // 400 years have 12 months === 4800 |
|
4160 return days * 4800 / 146097; |
|
4161 } |
|
4162 |
|
4163 function monthsToDays (months) { |
|
4164 // the reverse of daysToMonths |
|
4165 return months * 146097 / 4800; |
|
4166 } |
|
4167 |
|
4168 function as (units) { |
|
4169 if (!this.isValid()) { |
|
4170 return NaN; |
|
4171 } |
|
4172 var days; |
|
4173 var months; |
|
4174 var milliseconds = this._milliseconds; |
|
4175 |
|
4176 units = normalizeUnits(units); |
|
4177 |
|
4178 if (units === 'month' || units === 'year') { |
|
4179 days = this._days + milliseconds / 864e5; |
|
4180 months = this._months + daysToMonths(days); |
|
4181 return units === 'month' ? months : months / 12; |
|
4182 } else { |
|
4183 // handle milliseconds separately because of floating point math errors (issue #1867) |
|
4184 days = this._days + Math.round(monthsToDays(this._months)); |
|
4185 switch (units) { |
|
4186 case 'week' : return days / 7 + milliseconds / 6048e5; |
|
4187 case 'day' : return days + milliseconds / 864e5; |
|
4188 case 'hour' : return days * 24 + milliseconds / 36e5; |
|
4189 case 'minute' : return days * 1440 + milliseconds / 6e4; |
|
4190 case 'second' : return days * 86400 + milliseconds / 1000; |
|
4191 // Math.floor prevents floating point math errors here |
|
4192 case 'millisecond': return Math.floor(days * 864e5) + milliseconds; |
|
4193 default: throw new Error('Unknown unit ' + units); |
|
4194 } |
|
4195 } |
|
4196 } |
|
4197 |
|
4198 // TODO: Use this.as('ms')? |
|
4199 function valueOf$1 () { |
|
4200 if (!this.isValid()) { |
|
4201 return NaN; |
|
4202 } |
|
4203 return ( |
|
4204 this._milliseconds + |
|
4205 this._days * 864e5 + |
|
4206 (this._months % 12) * 2592e6 + |
|
4207 toInt(this._months / 12) * 31536e6 |
|
4208 ); |
|
4209 } |
|
4210 |
|
4211 function makeAs (alias) { |
|
4212 return function () { |
|
4213 return this.as(alias); |
|
4214 }; |
|
4215 } |
|
4216 |
|
4217 var asMilliseconds = makeAs('ms'); |
|
4218 var asSeconds = makeAs('s'); |
|
4219 var asMinutes = makeAs('m'); |
|
4220 var asHours = makeAs('h'); |
|
4221 var asDays = makeAs('d'); |
|
4222 var asWeeks = makeAs('w'); |
|
4223 var asMonths = makeAs('M'); |
|
4224 var asYears = makeAs('y'); |
|
4225 |
|
4226 function clone$1 () { |
|
4227 return createDuration(this); |
|
4228 } |
|
4229 |
|
4230 function get$2 (units) { |
|
4231 units = normalizeUnits(units); |
|
4232 return this.isValid() ? this[units + 's']() : NaN; |
|
4233 } |
|
4234 |
|
4235 function makeGetter(name) { |
|
4236 return function () { |
|
4237 return this.isValid() ? this._data[name] : NaN; |
|
4238 }; |
|
4239 } |
|
4240 |
|
4241 var milliseconds = makeGetter('milliseconds'); |
|
4242 var seconds = makeGetter('seconds'); |
|
4243 var minutes = makeGetter('minutes'); |
|
4244 var hours = makeGetter('hours'); |
|
4245 var days = makeGetter('days'); |
|
4246 var months = makeGetter('months'); |
|
4247 var years = makeGetter('years'); |
|
4248 |
|
4249 function weeks () { |
|
4250 return absFloor(this.days() / 7); |
|
4251 } |
|
4252 |
|
4253 var round = Math.round; |
|
4254 var thresholds = { |
|
4255 ss: 44, // a few seconds to seconds |
|
4256 s : 45, // seconds to minute |
|
4257 m : 45, // minutes to hour |
|
4258 h : 22, // hours to day |
|
4259 d : 26, // days to month |
|
4260 M : 11 // months to year |
|
4261 }; |
|
4262 |
|
4263 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize |
|
4264 function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) { |
|
4265 return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture); |
|
4266 } |
|
4267 |
|
4268 function relativeTime$1 (posNegDuration, withoutSuffix, locale) { |
|
4269 var duration = createDuration(posNegDuration).abs(); |
|
4270 var seconds = round(duration.as('s')); |
|
4271 var minutes = round(duration.as('m')); |
|
4272 var hours = round(duration.as('h')); |
|
4273 var days = round(duration.as('d')); |
|
4274 var months = round(duration.as('M')); |
|
4275 var years = round(duration.as('y')); |
|
4276 |
|
4277 var a = seconds <= thresholds.ss && ['s', seconds] || |
|
4278 seconds < thresholds.s && ['ss', seconds] || |
|
4279 minutes <= 1 && ['m'] || |
|
4280 minutes < thresholds.m && ['mm', minutes] || |
|
4281 hours <= 1 && ['h'] || |
|
4282 hours < thresholds.h && ['hh', hours] || |
|
4283 days <= 1 && ['d'] || |
|
4284 days < thresholds.d && ['dd', days] || |
|
4285 months <= 1 && ['M'] || |
|
4286 months < thresholds.M && ['MM', months] || |
|
4287 years <= 1 && ['y'] || ['yy', years]; |
|
4288 |
|
4289 a[2] = withoutSuffix; |
|
4290 a[3] = +posNegDuration > 0; |
|
4291 a[4] = locale; |
|
4292 return substituteTimeAgo.apply(null, a); |
|
4293 } |
|
4294 |
|
4295 // This function allows you to set the rounding function for relative time strings |
|
4296 function getSetRelativeTimeRounding (roundingFunction) { |
|
4297 if (roundingFunction === undefined) { |
|
4298 return round; |
|
4299 } |
|
4300 if (typeof(roundingFunction) === 'function') { |
|
4301 round = roundingFunction; |
|
4302 return true; |
|
4303 } |
|
4304 return false; |
|
4305 } |
|
4306 |
|
4307 // This function allows you to set a threshold for relative time strings |
|
4308 function getSetRelativeTimeThreshold (threshold, limit) { |
|
4309 if (thresholds[threshold] === undefined) { |
|
4310 return false; |
|
4311 } |
|
4312 if (limit === undefined) { |
|
4313 return thresholds[threshold]; |
|
4314 } |
|
4315 thresholds[threshold] = limit; |
|
4316 if (threshold === 's') { |
|
4317 thresholds.ss = limit - 1; |
|
4318 } |
|
4319 return true; |
|
4320 } |
|
4321 |
|
4322 function humanize (withSuffix) { |
|
4323 if (!this.isValid()) { |
|
4324 return this.localeData().invalidDate(); |
|
4325 } |
|
4326 |
|
4327 var locale = this.localeData(); |
|
4328 var output = relativeTime$1(this, !withSuffix, locale); |
|
4329 |
|
4330 if (withSuffix) { |
|
4331 output = locale.pastFuture(+this, output); |
|
4332 } |
|
4333 |
|
4334 return locale.postformat(output); |
|
4335 } |
|
4336 |
|
4337 var abs$1 = Math.abs; |
|
4338 |
|
4339 function sign(x) { |
|
4340 return ((x > 0) - (x < 0)) || +x; |
|
4341 } |
|
4342 |
|
4343 function toISOString$1() { |
|
4344 // for ISO strings we do not use the normal bubbling rules: |
|
4345 // * milliseconds bubble up until they become hours |
|
4346 // * days do not bubble at all |
|
4347 // * months bubble up until they become years |
|
4348 // This is because there is no context-free conversion between hours and days |
|
4349 // (think of clock changes) |
|
4350 // and also not between days and months (28-31 days per month) |
|
4351 if (!this.isValid()) { |
|
4352 return this.localeData().invalidDate(); |
|
4353 } |
|
4354 |
|
4355 var seconds = abs$1(this._milliseconds) / 1000; |
|
4356 var days = abs$1(this._days); |
|
4357 var months = abs$1(this._months); |
|
4358 var minutes, hours, years; |
|
4359 |
|
4360 // 3600 seconds -> 60 minutes -> 1 hour |
|
4361 minutes = absFloor(seconds / 60); |
|
4362 hours = absFloor(minutes / 60); |
|
4363 seconds %= 60; |
|
4364 minutes %= 60; |
|
4365 |
|
4366 // 12 months -> 1 year |
|
4367 years = absFloor(months / 12); |
|
4368 months %= 12; |
|
4369 |
|
4370 |
|
4371 // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js |
|
4372 var Y = years; |
|
4373 var M = months; |
|
4374 var D = days; |
|
4375 var h = hours; |
|
4376 var m = minutes; |
|
4377 var s = seconds ? seconds.toFixed(3).replace(/\.?0+$/, '') : ''; |
|
4378 var total = this.asSeconds(); |
|
4379 |
|
4380 if (!total) { |
|
4381 // this is the same as C#'s (Noda) and python (isodate)... |
|
4382 // but not other JS (goog.date) |
|
4383 return 'P0D'; |
|
4384 } |
|
4385 |
|
4386 var totalSign = total < 0 ? '-' : ''; |
|
4387 var ymSign = sign(this._months) !== sign(total) ? '-' : ''; |
|
4388 var daysSign = sign(this._days) !== sign(total) ? '-' : ''; |
|
4389 var hmsSign = sign(this._milliseconds) !== sign(total) ? '-' : ''; |
|
4390 |
|
4391 return totalSign + 'P' + |
|
4392 (Y ? ymSign + Y + 'Y' : '') + |
|
4393 (M ? ymSign + M + 'M' : '') + |
|
4394 (D ? daysSign + D + 'D' : '') + |
|
4395 ((h || m || s) ? 'T' : '') + |
|
4396 (h ? hmsSign + h + 'H' : '') + |
|
4397 (m ? hmsSign + m + 'M' : '') + |
|
4398 (s ? hmsSign + s + 'S' : ''); |
|
4399 } |
|
4400 |
|
4401 var proto$2 = Duration.prototype; |
|
4402 |
|
4403 proto$2.isValid = isValid$1; |
|
4404 proto$2.abs = abs; |
|
4405 proto$2.add = add$1; |
|
4406 proto$2.subtract = subtract$1; |
|
4407 proto$2.as = as; |
|
4408 proto$2.asMilliseconds = asMilliseconds; |
|
4409 proto$2.asSeconds = asSeconds; |
|
4410 proto$2.asMinutes = asMinutes; |
|
4411 proto$2.asHours = asHours; |
|
4412 proto$2.asDays = asDays; |
|
4413 proto$2.asWeeks = asWeeks; |
|
4414 proto$2.asMonths = asMonths; |
|
4415 proto$2.asYears = asYears; |
|
4416 proto$2.valueOf = valueOf$1; |
|
4417 proto$2._bubble = bubble; |
|
4418 proto$2.clone = clone$1; |
|
4419 proto$2.get = get$2; |
|
4420 proto$2.milliseconds = milliseconds; |
|
4421 proto$2.seconds = seconds; |
|
4422 proto$2.minutes = minutes; |
|
4423 proto$2.hours = hours; |
|
4424 proto$2.days = days; |
|
4425 proto$2.weeks = weeks; |
|
4426 proto$2.months = months; |
|
4427 proto$2.years = years; |
|
4428 proto$2.humanize = humanize; |
|
4429 proto$2.toISOString = toISOString$1; |
|
4430 proto$2.toString = toISOString$1; |
|
4431 proto$2.toJSON = toISOString$1; |
|
4432 proto$2.locale = locale; |
|
4433 proto$2.localeData = localeData; |
|
4434 |
|
4435 proto$2.toIsoString = deprecate('toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)', toISOString$1); |
|
4436 proto$2.lang = lang; |
|
4437 |
|
4438 // Side effect imports |
|
4439 |
|
4440 // FORMATTING |
|
4441 |
|
4442 addFormatToken('X', 0, 0, 'unix'); |
|
4443 addFormatToken('x', 0, 0, 'valueOf'); |
|
4444 |
|
4445 // PARSING |
|
4446 |
|
4447 addRegexToken('x', matchSigned); |
|
4448 addRegexToken('X', matchTimestamp); |
|
4449 addParseToken('X', function (input, array, config) { |
|
4450 config._d = new Date(parseFloat(input, 10) * 1000); |
|
4451 }); |
|
4452 addParseToken('x', function (input, array, config) { |
|
4453 config._d = new Date(toInt(input)); |
|
4454 }); |
|
4455 |
|
4456 // Side effect imports |
|
4457 |
|
4458 |
|
4459 hooks.version = '2.22.2'; |
|
4460 |
|
4461 setHookCallback(createLocal); |
|
4462 |
|
4463 hooks.fn = proto; |
|
4464 hooks.min = min; |
|
4465 hooks.max = max; |
|
4466 hooks.now = now; |
|
4467 hooks.utc = createUTC; |
|
4468 hooks.unix = createUnix; |
|
4469 hooks.months = listMonths; |
|
4470 hooks.isDate = isDate; |
|
4471 hooks.locale = getSetGlobalLocale; |
|
4472 hooks.invalid = createInvalid; |
|
4473 hooks.duration = createDuration; |
|
4474 hooks.isMoment = isMoment; |
|
4475 hooks.weekdays = listWeekdays; |
|
4476 hooks.parseZone = createInZone; |
|
4477 hooks.localeData = getLocale; |
|
4478 hooks.isDuration = isDuration; |
|
4479 hooks.monthsShort = listMonthsShort; |
|
4480 hooks.weekdaysMin = listWeekdaysMin; |
|
4481 hooks.defineLocale = defineLocale; |
|
4482 hooks.updateLocale = updateLocale; |
|
4483 hooks.locales = listLocales; |
|
4484 hooks.weekdaysShort = listWeekdaysShort; |
|
4485 hooks.normalizeUnits = normalizeUnits; |
|
4486 hooks.relativeTimeRounding = getSetRelativeTimeRounding; |
|
4487 hooks.relativeTimeThreshold = getSetRelativeTimeThreshold; |
|
4488 hooks.calendarFormat = getCalendarFormat; |
|
4489 hooks.prototype = proto; |
|
4490 |
|
4491 // currently HTML5 input type only supports 24-hour formats |
|
4492 hooks.HTML5_FMT = { |
|
4493 DATETIME_LOCAL: 'YYYY-MM-DDTHH:mm', // <input type="datetime-local" /> |
|
4494 DATETIME_LOCAL_SECONDS: 'YYYY-MM-DDTHH:mm:ss', // <input type="datetime-local" step="1" /> |
|
4495 DATETIME_LOCAL_MS: 'YYYY-MM-DDTHH:mm:ss.SSS', // <input type="datetime-local" step="0.001" /> |
|
4496 DATE: 'YYYY-MM-DD', // <input type="date" /> |
|
4497 TIME: 'HH:mm', // <input type="time" /> |
|
4498 TIME_SECONDS: 'HH:mm:ss', // <input type="time" step="1" /> |
|
4499 TIME_MS: 'HH:mm:ss.SSS', // <input type="time" step="0.001" /> |
|
4500 WEEK: 'YYYY-[W]WW', // <input type="week" /> |
|
4501 MONTH: 'YYYY-MM' // <input type="month" /> |
|
4502 }; |
|
4503 |
|
4504 return hooks; |
|
4505 |
|
4506 }))); |