Mercurial > hg > NetworkVis
comparison d3s_examples/python-neo4jrestclient/static/platin/lib/momentjs/moment.js @ 8:18ef6948d689
new d3s examples
author | Dirk Wintergruen <dwinter@mpiwg-berlin.mpg.de> |
---|---|
date | Thu, 01 Oct 2015 17:17:27 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
7:45dad9e38c82 | 8:18ef6948d689 |
---|---|
1 //! moment.js | |
2 //! version : 2.5.1 | |
3 //! authors : Tim Wood, Iskren Chernev, Moment.js contributors | |
4 //! license : MIT | |
5 //! momentjs.com | |
6 | |
7 (function (undefined) { | |
8 | |
9 /************************************ | |
10 Constants | |
11 ************************************/ | |
12 | |
13 var moment, | |
14 VERSION = "2.5.1", | |
15 global = this, | |
16 round = Math.round, | |
17 i, | |
18 | |
19 YEAR = 0, | |
20 MONTH = 1, | |
21 DATE = 2, | |
22 HOUR = 3, | |
23 MINUTE = 4, | |
24 SECOND = 5, | |
25 MILLISECOND = 6, | |
26 | |
27 // internal storage for language config files | |
28 languages = {}, | |
29 | |
30 // moment internal properties | |
31 momentProperties = { | |
32 _isAMomentObject: null, | |
33 _i : null, | |
34 _f : null, | |
35 _l : null, | |
36 _strict : null, | |
37 _isUTC : null, | |
38 _offset : null, // optional. Combine with _isUTC | |
39 _pf : null, | |
40 _lang : null // optional | |
41 }, | |
42 | |
43 // check for nodeJS | |
44 hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'), | |
45 | |
46 // ASP.NET json date format regex | |
47 aspNetJsonRegex = /^\/?Date\((\-?\d+)/i, | |
48 aspNetTimeSpanJsonRegex = /(\-)?(?:(\d*)\.)?(\d+)\:(\d+)(?:\:(\d+)\.?(\d{3})?)?/, | |
49 | |
50 // from http://docs.closure-library.googlecode.com/git/closure_goog_date_date.js.source.html | |
51 // somewhat more in line with 4.4.3.2 2004 spec, but allows decimal anywhere | |
52 isoDurationRegex = /^(-)?P(?:(?:([0-9,.]*)Y)?(?:([0-9,.]*)M)?(?:([0-9,.]*)D)?(?:T(?:([0-9,.]*)H)?(?:([0-9,.]*)M)?(?:([0-9,.]*)S)?)?|([0-9,.]*)W)$/, | |
53 | |
54 // format tokens | |
55 formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|X|zz?|ZZ?|.)/g, | |
56 localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g, | |
57 | |
58 // parsing token regexes | |
59 parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99 | |
60 parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999 | |
61 parseTokenOneToFourDigits = /\d{1,4}/, // 0 - 9999 | |
62 parseTokenOneToSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999 | |
63 parseTokenDigits = /\d+/, // nonzero number of digits | |
64 parseTokenWord = /[0-9]*['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF\/]+(\s*?[\u0600-\u06FF]+){1,2}/i, // any word (or two) characters or numbers including two/three word month in arabic. | |
65 parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z | |
66 parseTokenT = /T/i, // T (ISO separator) | |
67 parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123 | |
68 | |
69 //strict parsing regexes | |
70 parseTokenOneDigit = /\d/, // 0 - 9 | |
71 parseTokenTwoDigits = /\d\d/, // 00 - 99 | |
72 parseTokenThreeDigits = /\d{3}/, // 000 - 999 | |
73 parseTokenFourDigits = /\d{4}/, // 0000 - 9999 | |
74 parseTokenSixDigits = /[+-]?\d{6}/, // -999,999 - 999,999 | |
75 parseTokenSignedNumber = /[+-]?\d+/, // -inf - inf | |
76 | |
77 // iso 8601 regex | |
78 // 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) | |
79 isoRegex = /^\s*(?:[+-]\d{6}|\d{4})-(?:(\d\d-\d\d)|(W\d\d$)|(W\d\d-\d)|(\d\d\d))((T| )(\d\d(:\d\d(:\d\d(\.\d+)?)?)?)?([\+\-]\d\d(?::?\d\d)?|\s*Z)?)?$/, | |
80 | |
81 isoFormat = 'YYYY-MM-DDTHH:mm:ssZ', | |
82 | |
83 isoDates = [ | |
84 ['YYYYYY-MM-DD', /[+-]\d{6}-\d{2}-\d{2}/], | |
85 ['YYYY-MM-DD', /\d{4}-\d{2}-\d{2}/], | |
86 ['GGGG-[W]WW-E', /\d{4}-W\d{2}-\d/], | |
87 ['GGGG-[W]WW', /\d{4}-W\d{2}/], | |
88 ['YYYY-DDD', /\d{4}-\d{3}/] | |
89 ], | |
90 | |
91 // iso time formats and regexes | |
92 isoTimes = [ | |
93 ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/], | |
94 ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/], | |
95 ['HH:mm', /(T| )\d\d:\d\d/], | |
96 ['HH', /(T| )\d\d/] | |
97 ], | |
98 | |
99 // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"] | |
100 parseTimezoneChunker = /([\+\-]|\d\d)/gi, | |
101 | |
102 // getter and setter names | |
103 proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'), | |
104 unitMillisecondFactors = { | |
105 'Milliseconds' : 1, | |
106 'Seconds' : 1e3, | |
107 'Minutes' : 6e4, | |
108 'Hours' : 36e5, | |
109 'Days' : 864e5, | |
110 'Months' : 2592e6, | |
111 'Years' : 31536e6 | |
112 }, | |
113 | |
114 unitAliases = { | |
115 ms : 'millisecond', | |
116 s : 'second', | |
117 m : 'minute', | |
118 h : 'hour', | |
119 d : 'day', | |
120 D : 'date', | |
121 w : 'week', | |
122 W : 'isoWeek', | |
123 M : 'month', | |
124 y : 'year', | |
125 DDD : 'dayOfYear', | |
126 e : 'weekday', | |
127 E : 'isoWeekday', | |
128 gg: 'weekYear', | |
129 GG: 'isoWeekYear' | |
130 }, | |
131 | |
132 camelFunctions = { | |
133 dayofyear : 'dayOfYear', | |
134 isoweekday : 'isoWeekday', | |
135 isoweek : 'isoWeek', | |
136 weekyear : 'weekYear', | |
137 isoweekyear : 'isoWeekYear' | |
138 }, | |
139 | |
140 // format function strings | |
141 formatFunctions = {}, | |
142 | |
143 // tokens to ordinalize and pad | |
144 ordinalizeTokens = 'DDD w W M D d'.split(' '), | |
145 paddedTokens = 'M D H h m s w W'.split(' '), | |
146 | |
147 formatTokenFunctions = { | |
148 M : function () { | |
149 return this.month() + 1; | |
150 }, | |
151 MMM : function (format) { | |
152 return this.lang().monthsShort(this, format); | |
153 }, | |
154 MMMM : function (format) { | |
155 return this.lang().months(this, format); | |
156 }, | |
157 D : function () { | |
158 return this.date(); | |
159 }, | |
160 DDD : function () { | |
161 return this.dayOfYear(); | |
162 }, | |
163 d : function () { | |
164 return this.day(); | |
165 }, | |
166 dd : function (format) { | |
167 return this.lang().weekdaysMin(this, format); | |
168 }, | |
169 ddd : function (format) { | |
170 return this.lang().weekdaysShort(this, format); | |
171 }, | |
172 dddd : function (format) { | |
173 return this.lang().weekdays(this, format); | |
174 }, | |
175 w : function () { | |
176 return this.week(); | |
177 }, | |
178 W : function () { | |
179 return this.isoWeek(); | |
180 }, | |
181 YY : function () { | |
182 return leftZeroFill(this.year() % 100, 2); | |
183 }, | |
184 YYYY : function () { | |
185 return leftZeroFill(this.year(), 4); | |
186 }, | |
187 YYYYY : function () { | |
188 return leftZeroFill(this.year(), 5); | |
189 }, | |
190 YYYYYY : function () { | |
191 var y = this.year(), sign = y >= 0 ? '+' : '-'; | |
192 return sign + leftZeroFill(Math.abs(y), 6); | |
193 }, | |
194 gg : function () { | |
195 return leftZeroFill(this.weekYear() % 100, 2); | |
196 }, | |
197 gggg : function () { | |
198 return leftZeroFill(this.weekYear(), 4); | |
199 }, | |
200 ggggg : function () { | |
201 return leftZeroFill(this.weekYear(), 5); | |
202 }, | |
203 GG : function () { | |
204 return leftZeroFill(this.isoWeekYear() % 100, 2); | |
205 }, | |
206 GGGG : function () { | |
207 return leftZeroFill(this.isoWeekYear(), 4); | |
208 }, | |
209 GGGGG : function () { | |
210 return leftZeroFill(this.isoWeekYear(), 5); | |
211 }, | |
212 e : function () { | |
213 return this.weekday(); | |
214 }, | |
215 E : function () { | |
216 return this.isoWeekday(); | |
217 }, | |
218 a : function () { | |
219 return this.lang().meridiem(this.hours(), this.minutes(), true); | |
220 }, | |
221 A : function () { | |
222 return this.lang().meridiem(this.hours(), this.minutes(), false); | |
223 }, | |
224 H : function () { | |
225 return this.hours(); | |
226 }, | |
227 h : function () { | |
228 return this.hours() % 12 || 12; | |
229 }, | |
230 m : function () { | |
231 return this.minutes(); | |
232 }, | |
233 s : function () { | |
234 return this.seconds(); | |
235 }, | |
236 S : function () { | |
237 return toInt(this.milliseconds() / 100); | |
238 }, | |
239 SS : function () { | |
240 return leftZeroFill(toInt(this.milliseconds() / 10), 2); | |
241 }, | |
242 SSS : function () { | |
243 return leftZeroFill(this.milliseconds(), 3); | |
244 }, | |
245 SSSS : function () { | |
246 return leftZeroFill(this.milliseconds(), 3); | |
247 }, | |
248 Z : function () { | |
249 var a = -this.zone(), | |
250 b = "+"; | |
251 if (a < 0) { | |
252 a = -a; | |
253 b = "-"; | |
254 } | |
255 return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2); | |
256 }, | |
257 ZZ : function () { | |
258 var a = -this.zone(), | |
259 b = "+"; | |
260 if (a < 0) { | |
261 a = -a; | |
262 b = "-"; | |
263 } | |
264 return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2); | |
265 }, | |
266 z : function () { | |
267 return this.zoneAbbr(); | |
268 }, | |
269 zz : function () { | |
270 return this.zoneName(); | |
271 }, | |
272 X : function () { | |
273 return this.unix(); | |
274 }, | |
275 Q : function () { | |
276 return this.quarter(); | |
277 } | |
278 }, | |
279 | |
280 lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin']; | |
281 | |
282 function defaultParsingFlags() { | |
283 // We need to deep clone this object, and es5 standard is not very | |
284 // helpful. | |
285 return { | |
286 empty : false, | |
287 unusedTokens : [], | |
288 unusedInput : [], | |
289 overflow : -2, | |
290 charsLeftOver : 0, | |
291 nullInput : false, | |
292 invalidMonth : null, | |
293 invalidFormat : false, | |
294 userInvalidated : false, | |
295 iso: false | |
296 }; | |
297 } | |
298 | |
299 function padToken(func, count) { | |
300 return function (a) { | |
301 return leftZeroFill(func.call(this, a), count); | |
302 }; | |
303 } | |
304 function ordinalizeToken(func, period) { | |
305 return function (a) { | |
306 return this.lang().ordinal(func.call(this, a), period); | |
307 }; | |
308 } | |
309 | |
310 while (ordinalizeTokens.length) { | |
311 i = ordinalizeTokens.pop(); | |
312 formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i); | |
313 } | |
314 while (paddedTokens.length) { | |
315 i = paddedTokens.pop(); | |
316 formatTokenFunctions[i + i] = padToken(formatTokenFunctions[i], 2); | |
317 } | |
318 formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3); | |
319 | |
320 | |
321 /************************************ | |
322 Constructors | |
323 ************************************/ | |
324 | |
325 function Language() { | |
326 | |
327 } | |
328 | |
329 // Moment prototype object | |
330 function Moment(config) { | |
331 checkOverflow(config); | |
332 extend(this, config); | |
333 } | |
334 | |
335 // Duration Constructor | |
336 function Duration(duration) { | |
337 var normalizedInput = normalizeObjectUnits(duration), | |
338 years = normalizedInput.year || 0, | |
339 months = normalizedInput.month || 0, | |
340 weeks = normalizedInput.week || 0, | |
341 days = normalizedInput.day || 0, | |
342 hours = normalizedInput.hour || 0, | |
343 minutes = normalizedInput.minute || 0, | |
344 seconds = normalizedInput.second || 0, | |
345 milliseconds = normalizedInput.millisecond || 0; | |
346 | |
347 // representation for dateAddRemove | |
348 this._milliseconds = +milliseconds + | |
349 seconds * 1e3 + // 1000 | |
350 minutes * 6e4 + // 1000 * 60 | |
351 hours * 36e5; // 1000 * 60 * 60 | |
352 // Because of dateAddRemove treats 24 hours as different from a | |
353 // day when working around DST, we need to store them separately | |
354 this._days = +days + | |
355 weeks * 7; | |
356 // It is impossible translate months into days without knowing | |
357 // which months you are are talking about, so we have to store | |
358 // it separately. | |
359 this._months = +months + | |
360 years * 12; | |
361 | |
362 this._data = {}; | |
363 | |
364 this._bubble(); | |
365 } | |
366 | |
367 /************************************ | |
368 Helpers | |
369 ************************************/ | |
370 | |
371 | |
372 function extend(a, b) { | |
373 for (var i in b) { | |
374 if (b.hasOwnProperty(i)) { | |
375 a[i] = b[i]; | |
376 } | |
377 } | |
378 | |
379 if (b.hasOwnProperty("toString")) { | |
380 a.toString = b.toString; | |
381 } | |
382 | |
383 if (b.hasOwnProperty("valueOf")) { | |
384 a.valueOf = b.valueOf; | |
385 } | |
386 | |
387 return a; | |
388 } | |
389 | |
390 function cloneMoment(m) { | |
391 var result = {}, i; | |
392 for (i in m) { | |
393 if (m.hasOwnProperty(i) && momentProperties.hasOwnProperty(i)) { | |
394 result[i] = m[i]; | |
395 } | |
396 } | |
397 | |
398 return result; | |
399 } | |
400 | |
401 function absRound(number) { | |
402 if (number < 0) { | |
403 return Math.ceil(number); | |
404 } else { | |
405 return Math.floor(number); | |
406 } | |
407 } | |
408 | |
409 // left zero fill a number | |
410 // see http://jsperf.com/left-zero-filling for performance comparison | |
411 function leftZeroFill(number, targetLength, forceSign) { | |
412 var output = '' + Math.abs(number), | |
413 sign = number >= 0; | |
414 | |
415 while (output.length < targetLength) { | |
416 output = '0' + output; | |
417 } | |
418 return (sign ? (forceSign ? '+' : '') : '-') + output; | |
419 } | |
420 | |
421 // helper function for _.addTime and _.subtractTime | |
422 function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) { | |
423 var milliseconds = duration._milliseconds, | |
424 days = duration._days, | |
425 months = duration._months, | |
426 minutes, | |
427 hours; | |
428 | |
429 if (milliseconds) { | |
430 mom._d.setTime(+mom._d + milliseconds * isAdding); | |
431 } | |
432 // store the minutes and hours so we can restore them | |
433 if (days || months) { | |
434 minutes = mom.minute(); | |
435 hours = mom.hour(); | |
436 } | |
437 if (days) { | |
438 mom.date(mom.date() + days * isAdding); | |
439 } | |
440 if (months) { | |
441 mom.month(mom.month() + months * isAdding); | |
442 } | |
443 if (milliseconds && !ignoreUpdateOffset) { | |
444 moment.updateOffset(mom); | |
445 } | |
446 // restore the minutes and hours after possibly changing dst | |
447 if (days || months) { | |
448 mom.minute(minutes); | |
449 mom.hour(hours); | |
450 } | |
451 } | |
452 | |
453 // check if is an array | |
454 function isArray(input) { | |
455 return Object.prototype.toString.call(input) === '[object Array]'; | |
456 } | |
457 | |
458 function isDate(input) { | |
459 return Object.prototype.toString.call(input) === '[object Date]' || | |
460 input instanceof Date; | |
461 } | |
462 | |
463 // compare two arrays, return the number of differences | |
464 function compareArrays(array1, array2, dontConvert) { | |
465 var len = Math.min(array1.length, array2.length), | |
466 lengthDiff = Math.abs(array1.length - array2.length), | |
467 diffs = 0, | |
468 i; | |
469 for (i = 0; i < len; i++) { | |
470 if ((dontConvert && array1[i] !== array2[i]) || | |
471 (!dontConvert && toInt(array1[i]) !== toInt(array2[i]))) { | |
472 diffs++; | |
473 } | |
474 } | |
475 return diffs + lengthDiff; | |
476 } | |
477 | |
478 function normalizeUnits(units) { | |
479 if (units) { | |
480 var lowered = units.toLowerCase().replace(/(.)s$/, '$1'); | |
481 units = unitAliases[units] || camelFunctions[lowered] || lowered; | |
482 } | |
483 return units; | |
484 } | |
485 | |
486 function normalizeObjectUnits(inputObject) { | |
487 var normalizedInput = {}, | |
488 normalizedProp, | |
489 prop; | |
490 | |
491 for (prop in inputObject) { | |
492 if (inputObject.hasOwnProperty(prop)) { | |
493 normalizedProp = normalizeUnits(prop); | |
494 if (normalizedProp) { | |
495 normalizedInput[normalizedProp] = inputObject[prop]; | |
496 } | |
497 } | |
498 } | |
499 | |
500 return normalizedInput; | |
501 } | |
502 | |
503 function makeList(field) { | |
504 var count, setter; | |
505 | |
506 if (field.indexOf('week') === 0) { | |
507 count = 7; | |
508 setter = 'day'; | |
509 } | |
510 else if (field.indexOf('month') === 0) { | |
511 count = 12; | |
512 setter = 'month'; | |
513 } | |
514 else { | |
515 return; | |
516 } | |
517 | |
518 moment[field] = function (format, index) { | |
519 var i, getter, | |
520 method = moment.fn._lang[field], | |
521 results = []; | |
522 | |
523 if (typeof format === 'number') { | |
524 index = format; | |
525 format = undefined; | |
526 } | |
527 | |
528 getter = function (i) { | |
529 var m = moment().utc().set(setter, i); | |
530 return method.call(moment.fn._lang, m, format || ''); | |
531 }; | |
532 | |
533 if (index != null) { | |
534 return getter(index); | |
535 } | |
536 else { | |
537 for (i = 0; i < count; i++) { | |
538 results.push(getter(i)); | |
539 } | |
540 return results; | |
541 } | |
542 }; | |
543 } | |
544 | |
545 function toInt(argumentForCoercion) { | |
546 var coercedNumber = +argumentForCoercion, | |
547 value = 0; | |
548 | |
549 if (coercedNumber !== 0 && isFinite(coercedNumber)) { | |
550 if (coercedNumber >= 0) { | |
551 value = Math.floor(coercedNumber); | |
552 } else { | |
553 value = Math.ceil(coercedNumber); | |
554 } | |
555 } | |
556 | |
557 return value; | |
558 } | |
559 | |
560 function daysInMonth(year, month) { | |
561 return new Date(Date.UTC(year, month + 1, 0)).getUTCDate(); | |
562 } | |
563 | |
564 function daysInYear(year) { | |
565 return isLeapYear(year) ? 366 : 365; | |
566 } | |
567 | |
568 function isLeapYear(year) { | |
569 return (year % 4 === 0 && year % 100 !== 0) || year % 400 === 0; | |
570 } | |
571 | |
572 function checkOverflow(m) { | |
573 var overflow; | |
574 if (m._a && m._pf.overflow === -2) { | |
575 overflow = | |
576 m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH : | |
577 m._a[DATE] < 1 || m._a[DATE] > daysInMonth(m._a[YEAR], m._a[MONTH]) ? DATE : | |
578 m._a[HOUR] < 0 || m._a[HOUR] > 23 ? HOUR : | |
579 m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE : | |
580 m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND : | |
581 m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND : | |
582 -1; | |
583 | |
584 if (m._pf._overflowDayOfYear && (overflow < YEAR || overflow > DATE)) { | |
585 overflow = DATE; | |
586 } | |
587 | |
588 m._pf.overflow = overflow; | |
589 } | |
590 } | |
591 | |
592 function isValid(m) { | |
593 if (m._isValid == null) { | |
594 m._isValid = !isNaN(m._d.getTime()) && | |
595 m._pf.overflow < 0 && | |
596 !m._pf.empty && | |
597 !m._pf.invalidMonth && | |
598 !m._pf.nullInput && | |
599 !m._pf.invalidFormat && | |
600 !m._pf.userInvalidated; | |
601 | |
602 if (m._strict) { | |
603 m._isValid = m._isValid && | |
604 m._pf.charsLeftOver === 0 && | |
605 m._pf.unusedTokens.length === 0; | |
606 } | |
607 } | |
608 return m._isValid; | |
609 } | |
610 | |
611 function normalizeLanguage(key) { | |
612 return key ? key.toLowerCase().replace('_', '-') : key; | |
613 } | |
614 | |
615 // Return a moment from input, that is local/utc/zone equivalent to model. | |
616 function makeAs(input, model) { | |
617 return model._isUTC ? moment(input).zone(model._offset || 0) : | |
618 moment(input).local(); | |
619 } | |
620 | |
621 /************************************ | |
622 Languages | |
623 ************************************/ | |
624 | |
625 | |
626 extend(Language.prototype, { | |
627 | |
628 set : function (config) { | |
629 var prop, i; | |
630 for (i in config) { | |
631 prop = config[i]; | |
632 if (typeof prop === 'function') { | |
633 this[i] = prop; | |
634 } else { | |
635 this['_' + i] = prop; | |
636 } | |
637 } | |
638 }, | |
639 | |
640 _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"), | |
641 months : function (m) { | |
642 return this._months[m.month()]; | |
643 }, | |
644 | |
645 _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"), | |
646 monthsShort : function (m) { | |
647 return this._monthsShort[m.month()]; | |
648 }, | |
649 | |
650 monthsParse : function (monthName) { | |
651 var i, mom, regex; | |
652 | |
653 if (!this._monthsParse) { | |
654 this._monthsParse = []; | |
655 } | |
656 | |
657 for (i = 0; i < 12; i++) { | |
658 // make the regex if we don't have it already | |
659 if (!this._monthsParse[i]) { | |
660 mom = moment.utc([2000, i]); | |
661 regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, ''); | |
662 this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i'); | |
663 } | |
664 // test the regex | |
665 if (this._monthsParse[i].test(monthName)) { | |
666 return i; | |
667 } | |
668 } | |
669 }, | |
670 | |
671 _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"), | |
672 weekdays : function (m) { | |
673 return this._weekdays[m.day()]; | |
674 }, | |
675 | |
676 _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"), | |
677 weekdaysShort : function (m) { | |
678 return this._weekdaysShort[m.day()]; | |
679 }, | |
680 | |
681 _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"), | |
682 weekdaysMin : function (m) { | |
683 return this._weekdaysMin[m.day()]; | |
684 }, | |
685 | |
686 weekdaysParse : function (weekdayName) { | |
687 var i, mom, regex; | |
688 | |
689 if (!this._weekdaysParse) { | |
690 this._weekdaysParse = []; | |
691 } | |
692 | |
693 for (i = 0; i < 7; i++) { | |
694 // make the regex if we don't have it already | |
695 if (!this._weekdaysParse[i]) { | |
696 mom = moment([2000, 1]).day(i); | |
697 regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, ''); | |
698 this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i'); | |
699 } | |
700 // test the regex | |
701 if (this._weekdaysParse[i].test(weekdayName)) { | |
702 return i; | |
703 } | |
704 } | |
705 }, | |
706 | |
707 _longDateFormat : { | |
708 LT : "h:mm A", | |
709 L : "MM/DD/YYYY", | |
710 LL : "MMMM D YYYY", | |
711 LLL : "MMMM D YYYY LT", | |
712 LLLL : "dddd, MMMM D YYYY LT" | |
713 }, | |
714 longDateFormat : function (key) { | |
715 var output = this._longDateFormat[key]; | |
716 if (!output && this._longDateFormat[key.toUpperCase()]) { | |
717 output = this._longDateFormat[key.toUpperCase()].replace(/MMMM|MM|DD|dddd/g, function (val) { | |
718 return val.slice(1); | |
719 }); | |
720 this._longDateFormat[key] = output; | |
721 } | |
722 return output; | |
723 }, | |
724 | |
725 isPM : function (input) { | |
726 // IE8 Quirks Mode & IE7 Standards Mode do not allow accessing strings like arrays | |
727 // Using charAt should be more compatible. | |
728 return ((input + '').toLowerCase().charAt(0) === 'p'); | |
729 }, | |
730 | |
731 _meridiemParse : /[ap]\.?m?\.?/i, | |
732 meridiem : function (hours, minutes, isLower) { | |
733 if (hours > 11) { | |
734 return isLower ? 'pm' : 'PM'; | |
735 } else { | |
736 return isLower ? 'am' : 'AM'; | |
737 } | |
738 }, | |
739 | |
740 _calendar : { | |
741 sameDay : '[Today at] LT', | |
742 nextDay : '[Tomorrow at] LT', | |
743 nextWeek : 'dddd [at] LT', | |
744 lastDay : '[Yesterday at] LT', | |
745 lastWeek : '[Last] dddd [at] LT', | |
746 sameElse : 'L' | |
747 }, | |
748 calendar : function (key, mom) { | |
749 var output = this._calendar[key]; | |
750 return typeof output === 'function' ? output.apply(mom) : output; | |
751 }, | |
752 | |
753 _relativeTime : { | |
754 future : "in %s", | |
755 past : "%s ago", | |
756 s : "a few seconds", | |
757 m : "a minute", | |
758 mm : "%d minutes", | |
759 h : "an hour", | |
760 hh : "%d hours", | |
761 d : "a day", | |
762 dd : "%d days", | |
763 M : "a month", | |
764 MM : "%d months", | |
765 y : "a year", | |
766 yy : "%d years" | |
767 }, | |
768 relativeTime : function (number, withoutSuffix, string, isFuture) { | |
769 var output = this._relativeTime[string]; | |
770 return (typeof output === 'function') ? | |
771 output(number, withoutSuffix, string, isFuture) : | |
772 output.replace(/%d/i, number); | |
773 }, | |
774 pastFuture : function (diff, output) { | |
775 var format = this._relativeTime[diff > 0 ? 'future' : 'past']; | |
776 return typeof format === 'function' ? format(output) : format.replace(/%s/i, output); | |
777 }, | |
778 | |
779 ordinal : function (number) { | |
780 return this._ordinal.replace("%d", number); | |
781 }, | |
782 _ordinal : "%d", | |
783 | |
784 preparse : function (string) { | |
785 return string; | |
786 }, | |
787 | |
788 postformat : function (string) { | |
789 return string; | |
790 }, | |
791 | |
792 week : function (mom) { | |
793 return weekOfYear(mom, this._week.dow, this._week.doy).week; | |
794 }, | |
795 | |
796 _week : { | |
797 dow : 0, // Sunday is the first day of the week. | |
798 doy : 6 // The week that contains Jan 1st is the first week of the year. | |
799 }, | |
800 | |
801 _invalidDate: 'Invalid date', | |
802 invalidDate: function () { | |
803 return this._invalidDate; | |
804 } | |
805 }); | |
806 | |
807 // Loads a language definition into the `languages` cache. The function | |
808 // takes a key and optionally values. If not in the browser and no values | |
809 // are provided, it will load the language file module. As a convenience, | |
810 // this function also returns the language values. | |
811 function loadLang(key, values) { | |
812 values.abbr = key; | |
813 if (!languages[key]) { | |
814 languages[key] = new Language(); | |
815 } | |
816 languages[key].set(values); | |
817 return languages[key]; | |
818 } | |
819 | |
820 // Remove a language from the `languages` cache. Mostly useful in tests. | |
821 function unloadLang(key) { | |
822 delete languages[key]; | |
823 } | |
824 | |
825 // Determines which language definition to use and returns it. | |
826 // | |
827 // With no parameters, it will return the global language. If you | |
828 // pass in a language key, such as 'en', it will return the | |
829 // definition for 'en', so long as 'en' has already been loaded using | |
830 // moment.lang. | |
831 function getLangDefinition(key) { | |
832 var i = 0, j, lang, next, split, | |
833 get = function (k) { | |
834 if (!languages[k] && hasModule) { | |
835 try { | |
836 require('./lang/' + k); | |
837 } catch (e) { } | |
838 } | |
839 return languages[k]; | |
840 }; | |
841 | |
842 if (!key) { | |
843 return moment.fn._lang; | |
844 } | |
845 | |
846 if (!isArray(key)) { | |
847 //short-circuit everything else | |
848 lang = get(key); | |
849 if (lang) { | |
850 return lang; | |
851 } | |
852 key = [key]; | |
853 } | |
854 | |
855 //pick the language from the array | |
856 //try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each | |
857 //substring from most specific to least, but move to the next array item if it's a more specific variant than the current root | |
858 while (i < key.length) { | |
859 split = normalizeLanguage(key[i]).split('-'); | |
860 j = split.length; | |
861 next = normalizeLanguage(key[i + 1]); | |
862 next = next ? next.split('-') : null; | |
863 while (j > 0) { | |
864 lang = get(split.slice(0, j).join('-')); | |
865 if (lang) { | |
866 return lang; | |
867 } | |
868 if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) { | |
869 //the next array item is better than a shallower substring of this one | |
870 break; | |
871 } | |
872 j--; | |
873 } | |
874 i++; | |
875 } | |
876 return moment.fn._lang; | |
877 } | |
878 | |
879 /************************************ | |
880 Formatting | |
881 ************************************/ | |
882 | |
883 | |
884 function removeFormattingTokens(input) { | |
885 if (input.match(/\[[\s\S]/)) { | |
886 return input.replace(/^\[|\]$/g, ""); | |
887 } | |
888 return input.replace(/\\/g, ""); | |
889 } | |
890 | |
891 function makeFormatFunction(format) { | |
892 var array = format.match(formattingTokens), i, length; | |
893 | |
894 for (i = 0, length = array.length; i < length; i++) { | |
895 if (formatTokenFunctions[array[i]]) { | |
896 array[i] = formatTokenFunctions[array[i]]; | |
897 } else { | |
898 array[i] = removeFormattingTokens(array[i]); | |
899 } | |
900 } | |
901 | |
902 return function (mom) { | |
903 var output = ""; | |
904 for (i = 0; i < length; i++) { | |
905 output += array[i] instanceof Function ? array[i].call(mom, format) : array[i]; | |
906 } | |
907 return output; | |
908 }; | |
909 } | |
910 | |
911 // format date using native date object | |
912 function formatMoment(m, format) { | |
913 | |
914 if (!m.isValid()) { | |
915 return m.lang().invalidDate(); | |
916 } | |
917 | |
918 format = expandFormat(format, m.lang()); | |
919 | |
920 if (!formatFunctions[format]) { | |
921 formatFunctions[format] = makeFormatFunction(format); | |
922 } | |
923 | |
924 return formatFunctions[format](m); | |
925 } | |
926 | |
927 function expandFormat(format, lang) { | |
928 var i = 5; | |
929 | |
930 function replaceLongDateFormatTokens(input) { | |
931 return lang.longDateFormat(input) || input; | |
932 } | |
933 | |
934 localFormattingTokens.lastIndex = 0; | |
935 while (i >= 0 && localFormattingTokens.test(format)) { | |
936 format = format.replace(localFormattingTokens, replaceLongDateFormatTokens); | |
937 localFormattingTokens.lastIndex = 0; | |
938 i -= 1; | |
939 } | |
940 | |
941 return format; | |
942 } | |
943 | |
944 | |
945 /************************************ | |
946 Parsing | |
947 ************************************/ | |
948 | |
949 | |
950 // get the regex to find the next token | |
951 function getParseRegexForToken(token, config) { | |
952 var a, strict = config._strict; | |
953 switch (token) { | |
954 case 'DDDD': | |
955 return parseTokenThreeDigits; | |
956 case 'YYYY': | |
957 case 'GGGG': | |
958 case 'gggg': | |
959 return strict ? parseTokenFourDigits : parseTokenOneToFourDigits; | |
960 case 'Y': | |
961 case 'G': | |
962 case 'g': | |
963 return parseTokenSignedNumber; | |
964 case 'YYYYYY': | |
965 case 'YYYYY': | |
966 case 'GGGGG': | |
967 case 'ggggg': | |
968 return strict ? parseTokenSixDigits : parseTokenOneToSixDigits; | |
969 case 'S': | |
970 if (strict) { return parseTokenOneDigit; } | |
971 /* falls through */ | |
972 case 'SS': | |
973 if (strict) { return parseTokenTwoDigits; } | |
974 /* falls through */ | |
975 case 'SSS': | |
976 if (strict) { return parseTokenThreeDigits; } | |
977 /* falls through */ | |
978 case 'DDD': | |
979 return parseTokenOneToThreeDigits; | |
980 case 'MMM': | |
981 case 'MMMM': | |
982 case 'dd': | |
983 case 'ddd': | |
984 case 'dddd': | |
985 return parseTokenWord; | |
986 case 'a': | |
987 case 'A': | |
988 return getLangDefinition(config._l)._meridiemParse; | |
989 case 'X': | |
990 return parseTokenTimestampMs; | |
991 case 'Z': | |
992 case 'ZZ': | |
993 return parseTokenTimezone; | |
994 case 'T': | |
995 return parseTokenT; | |
996 case 'SSSS': | |
997 return parseTokenDigits; | |
998 case 'MM': | |
999 case 'DD': | |
1000 case 'YY': | |
1001 case 'GG': | |
1002 case 'gg': | |
1003 case 'HH': | |
1004 case 'hh': | |
1005 case 'mm': | |
1006 case 'ss': | |
1007 case 'ww': | |
1008 case 'WW': | |
1009 return strict ? parseTokenTwoDigits : parseTokenOneOrTwoDigits; | |
1010 case 'M': | |
1011 case 'D': | |
1012 case 'd': | |
1013 case 'H': | |
1014 case 'h': | |
1015 case 'm': | |
1016 case 's': | |
1017 case 'w': | |
1018 case 'W': | |
1019 case 'e': | |
1020 case 'E': | |
1021 return parseTokenOneOrTwoDigits; | |
1022 default : | |
1023 a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i")); | |
1024 return a; | |
1025 } | |
1026 } | |
1027 | |
1028 function timezoneMinutesFromString(string) { | |
1029 string = string || ""; | |
1030 var possibleTzMatches = (string.match(parseTokenTimezone) || []), | |
1031 tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [], | |
1032 parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0], | |
1033 minutes = +(parts[1] * 60) + toInt(parts[2]); | |
1034 | |
1035 return parts[0] === '+' ? -minutes : minutes; | |
1036 } | |
1037 | |
1038 // function to convert string input to date | |
1039 function addTimeToArrayFromToken(token, input, config) { | |
1040 var a, datePartArray = config._a; | |
1041 | |
1042 switch (token) { | |
1043 // MONTH | |
1044 case 'M' : // fall through to MM | |
1045 case 'MM' : | |
1046 if (input != null) { | |
1047 datePartArray[MONTH] = toInt(input) - 1; | |
1048 } | |
1049 break; | |
1050 case 'MMM' : // fall through to MMMM | |
1051 case 'MMMM' : | |
1052 a = getLangDefinition(config._l).monthsParse(input); | |
1053 // if we didn't find a month name, mark the date as invalid. | |
1054 if (a != null) { | |
1055 datePartArray[MONTH] = a; | |
1056 } else { | |
1057 config._pf.invalidMonth = input; | |
1058 } | |
1059 break; | |
1060 // DAY OF MONTH | |
1061 case 'D' : // fall through to DD | |
1062 case 'DD' : | |
1063 if (input != null) { | |
1064 datePartArray[DATE] = toInt(input); | |
1065 } | |
1066 break; | |
1067 // DAY OF YEAR | |
1068 case 'DDD' : // fall through to DDDD | |
1069 case 'DDDD' : | |
1070 if (input != null) { | |
1071 config._dayOfYear = toInt(input); | |
1072 } | |
1073 | |
1074 break; | |
1075 // YEAR | |
1076 case 'YY' : | |
1077 datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000); | |
1078 break; | |
1079 case 'YYYY' : | |
1080 case 'YYYYY' : | |
1081 case 'YYYYYY' : | |
1082 datePartArray[YEAR] = toInt(input); | |
1083 break; | |
1084 // AM / PM | |
1085 case 'a' : // fall through to A | |
1086 case 'A' : | |
1087 config._isPm = getLangDefinition(config._l).isPM(input); | |
1088 break; | |
1089 // 24 HOUR | |
1090 case 'H' : // fall through to hh | |
1091 case 'HH' : // fall through to hh | |
1092 case 'h' : // fall through to hh | |
1093 case 'hh' : | |
1094 datePartArray[HOUR] = toInt(input); | |
1095 break; | |
1096 // MINUTE | |
1097 case 'm' : // fall through to mm | |
1098 case 'mm' : | |
1099 datePartArray[MINUTE] = toInt(input); | |
1100 break; | |
1101 // SECOND | |
1102 case 's' : // fall through to ss | |
1103 case 'ss' : | |
1104 datePartArray[SECOND] = toInt(input); | |
1105 break; | |
1106 // MILLISECOND | |
1107 case 'S' : | |
1108 case 'SS' : | |
1109 case 'SSS' : | |
1110 case 'SSSS' : | |
1111 datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000); | |
1112 break; | |
1113 // UNIX TIMESTAMP WITH MS | |
1114 case 'X': | |
1115 config._d = new Date(parseFloat(input) * 1000); | |
1116 break; | |
1117 // TIMEZONE | |
1118 case 'Z' : // fall through to ZZ | |
1119 case 'ZZ' : | |
1120 config._useUTC = true; | |
1121 config._tzm = timezoneMinutesFromString(input); | |
1122 break; | |
1123 case 'w': | |
1124 case 'ww': | |
1125 case 'W': | |
1126 case 'WW': | |
1127 case 'd': | |
1128 case 'dd': | |
1129 case 'ddd': | |
1130 case 'dddd': | |
1131 case 'e': | |
1132 case 'E': | |
1133 token = token.substr(0, 1); | |
1134 /* falls through */ | |
1135 case 'gg': | |
1136 case 'gggg': | |
1137 case 'GG': | |
1138 case 'GGGG': | |
1139 case 'GGGGG': | |
1140 token = token.substr(0, 2); | |
1141 if (input) { | |
1142 config._w = config._w || {}; | |
1143 config._w[token] = input; | |
1144 } | |
1145 break; | |
1146 } | |
1147 } | |
1148 | |
1149 // convert an array to a date. | |
1150 // the array should mirror the parameters below | |
1151 // note: all values past the year are optional and will default to the lowest possible value. | |
1152 // [year, month, day , hour, minute, second, millisecond] | |
1153 function dateFromConfig(config) { | |
1154 var i, date, input = [], currentDate, | |
1155 yearToUse, fixYear, w, temp, lang, weekday, week; | |
1156 | |
1157 if (config._d) { | |
1158 return; | |
1159 } | |
1160 | |
1161 currentDate = currentDateArray(config); | |
1162 | |
1163 //compute day of the year from weeks and weekdays | |
1164 if (config._w && config._a[DATE] == null && config._a[MONTH] == null) { | |
1165 fixYear = function (val) { | |
1166 var int_val = parseInt(val, 10); | |
1167 return val ? | |
1168 (val.length < 3 ? (int_val > 68 ? 1900 + int_val : 2000 + int_val) : int_val) : | |
1169 (config._a[YEAR] == null ? moment().weekYear() : config._a[YEAR]); | |
1170 }; | |
1171 | |
1172 w = config._w; | |
1173 if (w.GG != null || w.W != null || w.E != null) { | |
1174 temp = dayOfYearFromWeeks(fixYear(w.GG), w.W || 1, w.E, 4, 1); | |
1175 } | |
1176 else { | |
1177 lang = getLangDefinition(config._l); | |
1178 weekday = w.d != null ? parseWeekday(w.d, lang) : | |
1179 (w.e != null ? parseInt(w.e, 10) + lang._week.dow : 0); | |
1180 | |
1181 week = parseInt(w.w, 10) || 1; | |
1182 | |
1183 //if we're parsing 'd', then the low day numbers may be next week | |
1184 if (w.d != null && weekday < lang._week.dow) { | |
1185 week++; | |
1186 } | |
1187 | |
1188 temp = dayOfYearFromWeeks(fixYear(w.gg), week, weekday, lang._week.doy, lang._week.dow); | |
1189 } | |
1190 | |
1191 config._a[YEAR] = temp.year; | |
1192 config._dayOfYear = temp.dayOfYear; | |
1193 } | |
1194 | |
1195 //if the day of the year is set, figure out what it is | |
1196 if (config._dayOfYear) { | |
1197 yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR]; | |
1198 | |
1199 if (config._dayOfYear > daysInYear(yearToUse)) { | |
1200 config._pf._overflowDayOfYear = true; | |
1201 } | |
1202 | |
1203 date = makeUTCDate(yearToUse, 0, config._dayOfYear); | |
1204 config._a[MONTH] = date.getUTCMonth(); | |
1205 config._a[DATE] = date.getUTCDate(); | |
1206 } | |
1207 | |
1208 // Default to current date. | |
1209 // * if no year, month, day of month are given, default to today | |
1210 // * if day of month is given, default month and year | |
1211 // * if month is given, default only year | |
1212 // * if year is given, don't default anything | |
1213 for (i = 0; i < 3 && config._a[i] == null; ++i) { | |
1214 config._a[i] = input[i] = currentDate[i]; | |
1215 } | |
1216 | |
1217 // Zero out whatever was not defaulted, including time | |
1218 for (; i < 7; i++) { | |
1219 config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i]; | |
1220 } | |
1221 | |
1222 // add the offsets to the time to be parsed so that we can have a clean array for checking isValid | |
1223 input[HOUR] += toInt((config._tzm || 0) / 60); | |
1224 input[MINUTE] += toInt((config._tzm || 0) % 60); | |
1225 | |
1226 config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input); | |
1227 } | |
1228 | |
1229 function dateFromObject(config) { | |
1230 var normalizedInput; | |
1231 | |
1232 if (config._d) { | |
1233 return; | |
1234 } | |
1235 | |
1236 normalizedInput = normalizeObjectUnits(config._i); | |
1237 config._a = [ | |
1238 normalizedInput.year, | |
1239 normalizedInput.month, | |
1240 normalizedInput.day, | |
1241 normalizedInput.hour, | |
1242 normalizedInput.minute, | |
1243 normalizedInput.second, | |
1244 normalizedInput.millisecond | |
1245 ]; | |
1246 | |
1247 dateFromConfig(config); | |
1248 } | |
1249 | |
1250 function currentDateArray(config) { | |
1251 var now = new Date(); | |
1252 if (config._useUTC) { | |
1253 return [ | |
1254 now.getUTCFullYear(), | |
1255 now.getUTCMonth(), | |
1256 now.getUTCDate() | |
1257 ]; | |
1258 } else { | |
1259 return [now.getFullYear(), now.getMonth(), now.getDate()]; | |
1260 } | |
1261 } | |
1262 | |
1263 // date from string and format string | |
1264 function makeDateFromStringAndFormat(config) { | |
1265 | |
1266 config._a = []; | |
1267 config._pf.empty = true; | |
1268 | |
1269 // This array is used to make a Date, either with `new Date` or `Date.UTC` | |
1270 var lang = getLangDefinition(config._l), | |
1271 string = '' + config._i, | |
1272 i, parsedInput, tokens, token, skipped, | |
1273 stringLength = string.length, | |
1274 totalParsedInputLength = 0; | |
1275 | |
1276 tokens = expandFormat(config._f, lang).match(formattingTokens) || []; | |
1277 | |
1278 for (i = 0; i < tokens.length; i++) { | |
1279 token = tokens[i]; | |
1280 parsedInput = (string.match(getParseRegexForToken(token, config)) || [])[0]; | |
1281 if (parsedInput) { | |
1282 skipped = string.substr(0, string.indexOf(parsedInput)); | |
1283 if (skipped.length > 0) { | |
1284 config._pf.unusedInput.push(skipped); | |
1285 } | |
1286 string = string.slice(string.indexOf(parsedInput) + parsedInput.length); | |
1287 totalParsedInputLength += parsedInput.length; | |
1288 } | |
1289 // don't parse if it's not a known token | |
1290 if (formatTokenFunctions[token]) { | |
1291 if (parsedInput) { | |
1292 config._pf.empty = false; | |
1293 } | |
1294 else { | |
1295 config._pf.unusedTokens.push(token); | |
1296 } | |
1297 addTimeToArrayFromToken(token, parsedInput, config); | |
1298 } | |
1299 else if (config._strict && !parsedInput) { | |
1300 config._pf.unusedTokens.push(token); | |
1301 } | |
1302 } | |
1303 | |
1304 // add remaining unparsed input length to the string | |
1305 config._pf.charsLeftOver = stringLength - totalParsedInputLength; | |
1306 if (string.length > 0) { | |
1307 config._pf.unusedInput.push(string); | |
1308 } | |
1309 | |
1310 // handle am pm | |
1311 if (config._isPm && config._a[HOUR] < 12) { | |
1312 config._a[HOUR] += 12; | |
1313 } | |
1314 // if is 12 am, change hours to 0 | |
1315 if (config._isPm === false && config._a[HOUR] === 12) { | |
1316 config._a[HOUR] = 0; | |
1317 } | |
1318 | |
1319 dateFromConfig(config); | |
1320 checkOverflow(config); | |
1321 } | |
1322 | |
1323 function unescapeFormat(s) { | |
1324 return s.replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g, function (matched, p1, p2, p3, p4) { | |
1325 return p1 || p2 || p3 || p4; | |
1326 }); | |
1327 } | |
1328 | |
1329 // Code from http://stackoverflow.com/questions/3561493/is-there-a-regexp-escape-function-in-javascript | |
1330 function regexpEscape(s) { | |
1331 return s.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); | |
1332 } | |
1333 | |
1334 // date from string and array of format strings | |
1335 function makeDateFromStringAndArray(config) { | |
1336 var tempConfig, | |
1337 bestMoment, | |
1338 | |
1339 scoreToBeat, | |
1340 i, | |
1341 currentScore; | |
1342 | |
1343 if (config._f.length === 0) { | |
1344 config._pf.invalidFormat = true; | |
1345 config._d = new Date(NaN); | |
1346 return; | |
1347 } | |
1348 | |
1349 for (i = 0; i < config._f.length; i++) { | |
1350 currentScore = 0; | |
1351 tempConfig = extend({}, config); | |
1352 tempConfig._pf = defaultParsingFlags(); | |
1353 tempConfig._f = config._f[i]; | |
1354 makeDateFromStringAndFormat(tempConfig); | |
1355 | |
1356 if (!isValid(tempConfig)) { | |
1357 continue; | |
1358 } | |
1359 | |
1360 // if there is any input that was not parsed add a penalty for that format | |
1361 currentScore += tempConfig._pf.charsLeftOver; | |
1362 | |
1363 //or tokens | |
1364 currentScore += tempConfig._pf.unusedTokens.length * 10; | |
1365 | |
1366 tempConfig._pf.score = currentScore; | |
1367 | |
1368 if (scoreToBeat == null || currentScore < scoreToBeat) { | |
1369 scoreToBeat = currentScore; | |
1370 bestMoment = tempConfig; | |
1371 } | |
1372 } | |
1373 | |
1374 extend(config, bestMoment || tempConfig); | |
1375 } | |
1376 | |
1377 // date from iso format | |
1378 function makeDateFromString(config) { | |
1379 var i, l, | |
1380 string = config._i, | |
1381 match = isoRegex.exec(string); | |
1382 | |
1383 if (match) { | |
1384 config._pf.iso = true; | |
1385 for (i = 0, l = isoDates.length; i < l; i++) { | |
1386 if (isoDates[i][1].exec(string)) { | |
1387 // match[5] should be "T" or undefined | |
1388 config._f = isoDates[i][0] + (match[6] || " "); | |
1389 break; | |
1390 } | |
1391 } | |
1392 for (i = 0, l = isoTimes.length; i < l; i++) { | |
1393 if (isoTimes[i][1].exec(string)) { | |
1394 config._f += isoTimes[i][0]; | |
1395 break; | |
1396 } | |
1397 } | |
1398 if (string.match(parseTokenTimezone)) { | |
1399 config._f += "Z"; | |
1400 } | |
1401 makeDateFromStringAndFormat(config); | |
1402 } | |
1403 else { | |
1404 config._d = new Date(string); | |
1405 } | |
1406 } | |
1407 | |
1408 function makeDateFromInput(config) { | |
1409 var input = config._i, | |
1410 matched = aspNetJsonRegex.exec(input); | |
1411 | |
1412 if (input === undefined) { | |
1413 config._d = new Date(); | |
1414 } else if (matched) { | |
1415 config._d = new Date(+matched[1]); | |
1416 } else if (typeof input === 'string') { | |
1417 makeDateFromString(config); | |
1418 } else if (isArray(input)) { | |
1419 config._a = input.slice(0); | |
1420 dateFromConfig(config); | |
1421 } else if (isDate(input)) { | |
1422 config._d = new Date(+input); | |
1423 } else if (typeof(input) === 'object') { | |
1424 dateFromObject(config); | |
1425 } else { | |
1426 config._d = new Date(input); | |
1427 } | |
1428 } | |
1429 | |
1430 function makeDate(y, m, d, h, M, s, ms) { | |
1431 //can't just apply() to create a date: | |
1432 //http://stackoverflow.com/questions/181348/instantiating-a-javascript-object-by-calling-prototype-constructor-apply | |
1433 var date = new Date(y, m, d, h, M, s, ms); | |
1434 | |
1435 //the date constructor doesn't accept years < 1970 | |
1436 if (y < 1970) { | |
1437 date.setFullYear(y); | |
1438 } | |
1439 return date; | |
1440 } | |
1441 | |
1442 function makeUTCDate(y) { | |
1443 var date = new Date(Date.UTC.apply(null, arguments)); | |
1444 if (y < 1970) { | |
1445 date.setUTCFullYear(y); | |
1446 } | |
1447 return date; | |
1448 } | |
1449 | |
1450 function parseWeekday(input, language) { | |
1451 if (typeof input === 'string') { | |
1452 if (!isNaN(input)) { | |
1453 input = parseInt(input, 10); | |
1454 } | |
1455 else { | |
1456 input = language.weekdaysParse(input); | |
1457 if (typeof input !== 'number') { | |
1458 return null; | |
1459 } | |
1460 } | |
1461 } | |
1462 return input; | |
1463 } | |
1464 | |
1465 /************************************ | |
1466 Relative Time | |
1467 ************************************/ | |
1468 | |
1469 | |
1470 // helper function for moment.fn.from, moment.fn.fromNow, and moment.duration.fn.humanize | |
1471 function substituteTimeAgo(string, number, withoutSuffix, isFuture, lang) { | |
1472 return lang.relativeTime(number || 1, !!withoutSuffix, string, isFuture); | |
1473 } | |
1474 | |
1475 function relativeTime(milliseconds, withoutSuffix, lang) { | |
1476 var seconds = round(Math.abs(milliseconds) / 1000), | |
1477 minutes = round(seconds / 60), | |
1478 hours = round(minutes / 60), | |
1479 days = round(hours / 24), | |
1480 years = round(days / 365), | |
1481 args = seconds < 45 && ['s', seconds] || | |
1482 minutes === 1 && ['m'] || | |
1483 minutes < 45 && ['mm', minutes] || | |
1484 hours === 1 && ['h'] || | |
1485 hours < 22 && ['hh', hours] || | |
1486 days === 1 && ['d'] || | |
1487 days <= 25 && ['dd', days] || | |
1488 days <= 45 && ['M'] || | |
1489 days < 345 && ['MM', round(days / 30)] || | |
1490 years === 1 && ['y'] || ['yy', years]; | |
1491 args[2] = withoutSuffix; | |
1492 args[3] = milliseconds > 0; | |
1493 args[4] = lang; | |
1494 return substituteTimeAgo.apply({}, args); | |
1495 } | |
1496 | |
1497 | |
1498 /************************************ | |
1499 Week of Year | |
1500 ************************************/ | |
1501 | |
1502 | |
1503 // firstDayOfWeek 0 = sun, 6 = sat | |
1504 // the day of the week that starts the week | |
1505 // (usually sunday or monday) | |
1506 // firstDayOfWeekOfYear 0 = sun, 6 = sat | |
1507 // the first week is the week that contains the first | |
1508 // of this day of the week | |
1509 // (eg. ISO weeks use thursday (4)) | |
1510 function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) { | |
1511 var end = firstDayOfWeekOfYear - firstDayOfWeek, | |
1512 daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(), | |
1513 adjustedMoment; | |
1514 | |
1515 | |
1516 if (daysToDayOfWeek > end) { | |
1517 daysToDayOfWeek -= 7; | |
1518 } | |
1519 | |
1520 if (daysToDayOfWeek < end - 7) { | |
1521 daysToDayOfWeek += 7; | |
1522 } | |
1523 | |
1524 adjustedMoment = moment(mom).add('d', daysToDayOfWeek); | |
1525 return { | |
1526 week: Math.ceil(adjustedMoment.dayOfYear() / 7), | |
1527 year: adjustedMoment.year() | |
1528 }; | |
1529 } | |
1530 | |
1531 //http://en.wikipedia.org/wiki/ISO_week_date#Calculating_a_date_given_the_year.2C_week_number_and_weekday | |
1532 function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) { | |
1533 var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear; | |
1534 | |
1535 weekday = weekday != null ? weekday : firstDayOfWeek; | |
1536 daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0); | |
1537 dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1; | |
1538 | |
1539 return { | |
1540 year: dayOfYear > 0 ? year : year - 1, | |
1541 dayOfYear: dayOfYear > 0 ? dayOfYear : daysInYear(year - 1) + dayOfYear | |
1542 }; | |
1543 } | |
1544 | |
1545 /************************************ | |
1546 Top Level Functions | |
1547 ************************************/ | |
1548 | |
1549 function makeMoment(config) { | |
1550 var input = config._i, | |
1551 format = config._f; | |
1552 | |
1553 if (input === null) { | |
1554 return moment.invalid({nullInput: true}); | |
1555 } | |
1556 | |
1557 if (typeof input === 'string') { | |
1558 config._i = input = getLangDefinition().preparse(input); | |
1559 } | |
1560 | |
1561 if (moment.isMoment(input)) { | |
1562 config = cloneMoment(input); | |
1563 | |
1564 config._d = new Date(+input._d); | |
1565 } else if (format) { | |
1566 if (isArray(format)) { | |
1567 makeDateFromStringAndArray(config); | |
1568 } else { | |
1569 makeDateFromStringAndFormat(config); | |
1570 } | |
1571 } else { | |
1572 makeDateFromInput(config); | |
1573 } | |
1574 | |
1575 return new Moment(config); | |
1576 } | |
1577 | |
1578 moment = function (input, format, lang, strict) { | |
1579 var c; | |
1580 | |
1581 if (typeof(lang) === "boolean") { | |
1582 strict = lang; | |
1583 lang = undefined; | |
1584 } | |
1585 // object construction must be done this way. | |
1586 // https://github.com/moment/moment/issues/1423 | |
1587 c = {}; | |
1588 c._isAMomentObject = true; | |
1589 c._i = input; | |
1590 c._f = format; | |
1591 c._l = lang; | |
1592 c._strict = strict; | |
1593 c._isUTC = false; | |
1594 c._pf = defaultParsingFlags(); | |
1595 | |
1596 return makeMoment(c); | |
1597 }; | |
1598 | |
1599 // creating with utc | |
1600 moment.utc = function (input, format, lang, strict) { | |
1601 var c; | |
1602 | |
1603 if (typeof(lang) === "boolean") { | |
1604 strict = lang; | |
1605 lang = undefined; | |
1606 } | |
1607 // object construction must be done this way. | |
1608 // https://github.com/moment/moment/issues/1423 | |
1609 c = {}; | |
1610 c._isAMomentObject = true; | |
1611 c._useUTC = true; | |
1612 c._isUTC = true; | |
1613 c._l = lang; | |
1614 c._i = input; | |
1615 c._f = format; | |
1616 c._strict = strict; | |
1617 c._pf = defaultParsingFlags(); | |
1618 | |
1619 return makeMoment(c).utc(); | |
1620 }; | |
1621 | |
1622 // creating with unix timestamp (in seconds) | |
1623 moment.unix = function (input) { | |
1624 return moment(input * 1000); | |
1625 }; | |
1626 | |
1627 // duration | |
1628 moment.duration = function (input, key) { | |
1629 var duration = input, | |
1630 // matching against regexp is expensive, do it on demand | |
1631 match = null, | |
1632 sign, | |
1633 ret, | |
1634 parseIso; | |
1635 | |
1636 if (moment.isDuration(input)) { | |
1637 duration = { | |
1638 ms: input._milliseconds, | |
1639 d: input._days, | |
1640 M: input._months | |
1641 }; | |
1642 } else if (typeof input === 'number') { | |
1643 duration = {}; | |
1644 if (key) { | |
1645 duration[key] = input; | |
1646 } else { | |
1647 duration.milliseconds = input; | |
1648 } | |
1649 } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) { | |
1650 sign = (match[1] === "-") ? -1 : 1; | |
1651 duration = { | |
1652 y: 0, | |
1653 d: toInt(match[DATE]) * sign, | |
1654 h: toInt(match[HOUR]) * sign, | |
1655 m: toInt(match[MINUTE]) * sign, | |
1656 s: toInt(match[SECOND]) * sign, | |
1657 ms: toInt(match[MILLISECOND]) * sign | |
1658 }; | |
1659 } else if (!!(match = isoDurationRegex.exec(input))) { | |
1660 sign = (match[1] === "-") ? -1 : 1; | |
1661 parseIso = function (inp) { | |
1662 // We'd normally use ~~inp for this, but unfortunately it also | |
1663 // converts floats to ints. | |
1664 // inp may be undefined, so careful calling replace on it. | |
1665 var res = inp && parseFloat(inp.replace(',', '.')); | |
1666 // apply sign while we're at it | |
1667 return (isNaN(res) ? 0 : res) * sign; | |
1668 }; | |
1669 duration = { | |
1670 y: parseIso(match[2]), | |
1671 M: parseIso(match[3]), | |
1672 d: parseIso(match[4]), | |
1673 h: parseIso(match[5]), | |
1674 m: parseIso(match[6]), | |
1675 s: parseIso(match[7]), | |
1676 w: parseIso(match[8]) | |
1677 }; | |
1678 } | |
1679 | |
1680 ret = new Duration(duration); | |
1681 | |
1682 if (moment.isDuration(input) && input.hasOwnProperty('_lang')) { | |
1683 ret._lang = input._lang; | |
1684 } | |
1685 | |
1686 return ret; | |
1687 }; | |
1688 | |
1689 // version number | |
1690 moment.version = VERSION; | |
1691 | |
1692 // default format | |
1693 moment.defaultFormat = isoFormat; | |
1694 | |
1695 // This function will be called whenever a moment is mutated. | |
1696 // It is intended to keep the offset in sync with the timezone. | |
1697 moment.updateOffset = function () {}; | |
1698 | |
1699 // This function will load languages and then set the global language. If | |
1700 // no arguments are passed in, it will simply return the current global | |
1701 // language key. | |
1702 moment.lang = function (key, values) { | |
1703 var r; | |
1704 if (!key) { | |
1705 return moment.fn._lang._abbr; | |
1706 } | |
1707 if (values) { | |
1708 loadLang(normalizeLanguage(key), values); | |
1709 } else if (values === null) { | |
1710 unloadLang(key); | |
1711 key = 'en'; | |
1712 } else if (!languages[key]) { | |
1713 getLangDefinition(key); | |
1714 } | |
1715 r = moment.duration.fn._lang = moment.fn._lang = getLangDefinition(key); | |
1716 return r._abbr; | |
1717 }; | |
1718 | |
1719 // returns language data | |
1720 moment.langData = function (key) { | |
1721 if (key && key._lang && key._lang._abbr) { | |
1722 key = key._lang._abbr; | |
1723 } | |
1724 return getLangDefinition(key); | |
1725 }; | |
1726 | |
1727 // compare moment object | |
1728 moment.isMoment = function (obj) { | |
1729 return obj instanceof Moment || | |
1730 (obj != null && obj.hasOwnProperty('_isAMomentObject')); | |
1731 }; | |
1732 | |
1733 // for typechecking Duration objects | |
1734 moment.isDuration = function (obj) { | |
1735 return obj instanceof Duration; | |
1736 }; | |
1737 | |
1738 for (i = lists.length - 1; i >= 0; --i) { | |
1739 makeList(lists[i]); | |
1740 } | |
1741 | |
1742 moment.normalizeUnits = function (units) { | |
1743 return normalizeUnits(units); | |
1744 }; | |
1745 | |
1746 moment.invalid = function (flags) { | |
1747 var m = moment.utc(NaN); | |
1748 if (flags != null) { | |
1749 extend(m._pf, flags); | |
1750 } | |
1751 else { | |
1752 m._pf.userInvalidated = true; | |
1753 } | |
1754 | |
1755 return m; | |
1756 }; | |
1757 | |
1758 moment.parseZone = function (input) { | |
1759 return moment(input).parseZone(); | |
1760 }; | |
1761 | |
1762 /************************************ | |
1763 Moment Prototype | |
1764 ************************************/ | |
1765 | |
1766 | |
1767 extend(moment.fn = Moment.prototype, { | |
1768 | |
1769 clone : function () { | |
1770 return moment(this); | |
1771 }, | |
1772 | |
1773 valueOf : function () { | |
1774 return +this._d + ((this._offset || 0) * 60000); | |
1775 }, | |
1776 | |
1777 unix : function () { | |
1778 return Math.floor(+this / 1000); | |
1779 }, | |
1780 | |
1781 toString : function () { | |
1782 return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ"); | |
1783 }, | |
1784 | |
1785 toDate : function () { | |
1786 return this._offset ? new Date(+this) : this._d; | |
1787 }, | |
1788 | |
1789 toISOString : function () { | |
1790 var m = moment(this).utc(); | |
1791 if (0 < m.year() && m.year() <= 9999) { | |
1792 return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); | |
1793 } else { | |
1794 return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]'); | |
1795 } | |
1796 }, | |
1797 | |
1798 toArray : function () { | |
1799 var m = this; | |
1800 return [ | |
1801 m.year(), | |
1802 m.month(), | |
1803 m.date(), | |
1804 m.hours(), | |
1805 m.minutes(), | |
1806 m.seconds(), | |
1807 m.milliseconds() | |
1808 ]; | |
1809 }, | |
1810 | |
1811 isValid : function () { | |
1812 return isValid(this); | |
1813 }, | |
1814 | |
1815 isDSTShifted : function () { | |
1816 | |
1817 if (this._a) { | |
1818 return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0; | |
1819 } | |
1820 | |
1821 return false; | |
1822 }, | |
1823 | |
1824 parsingFlags : function () { | |
1825 return extend({}, this._pf); | |
1826 }, | |
1827 | |
1828 invalidAt: function () { | |
1829 return this._pf.overflow; | |
1830 }, | |
1831 | |
1832 utc : function () { | |
1833 return this.zone(0); | |
1834 }, | |
1835 | |
1836 local : function () { | |
1837 this.zone(0); | |
1838 this._isUTC = false; | |
1839 return this; | |
1840 }, | |
1841 | |
1842 format : function (inputString) { | |
1843 var output = formatMoment(this, inputString || moment.defaultFormat); | |
1844 return this.lang().postformat(output); | |
1845 }, | |
1846 | |
1847 add : function (input, val) { | |
1848 var dur; | |
1849 // switch args to support add('s', 1) and add(1, 's') | |
1850 if (typeof input === 'string') { | |
1851 dur = moment.duration(+val, input); | |
1852 } else { | |
1853 dur = moment.duration(input, val); | |
1854 } | |
1855 addOrSubtractDurationFromMoment(this, dur, 1); | |
1856 return this; | |
1857 }, | |
1858 | |
1859 subtract : function (input, val) { | |
1860 var dur; | |
1861 // switch args to support subtract('s', 1) and subtract(1, 's') | |
1862 if (typeof input === 'string') { | |
1863 dur = moment.duration(+val, input); | |
1864 } else { | |
1865 dur = moment.duration(input, val); | |
1866 } | |
1867 addOrSubtractDurationFromMoment(this, dur, -1); | |
1868 return this; | |
1869 }, | |
1870 | |
1871 diff : function (input, units, asFloat) { | |
1872 var that = makeAs(input, this), | |
1873 zoneDiff = (this.zone() - that.zone()) * 6e4, | |
1874 diff, output; | |
1875 | |
1876 units = normalizeUnits(units); | |
1877 | |
1878 if (units === 'year' || units === 'month') { | |
1879 // average number of days in the months in the given dates | |
1880 diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2 | |
1881 // difference in months | |
1882 output = ((this.year() - that.year()) * 12) + (this.month() - that.month()); | |
1883 // adjust by taking difference in days, average number of days | |
1884 // and dst in the given months. | |
1885 output += ((this - moment(this).startOf('month')) - | |
1886 (that - moment(that).startOf('month'))) / diff; | |
1887 // same as above but with zones, to negate all dst | |
1888 output -= ((this.zone() - moment(this).startOf('month').zone()) - | |
1889 (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff; | |
1890 if (units === 'year') { | |
1891 output = output / 12; | |
1892 } | |
1893 } else { | |
1894 diff = (this - that); | |
1895 output = units === 'second' ? diff / 1e3 : // 1000 | |
1896 units === 'minute' ? diff / 6e4 : // 1000 * 60 | |
1897 units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60 | |
1898 units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst | |
1899 units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst | |
1900 diff; | |
1901 } | |
1902 return asFloat ? output : absRound(output); | |
1903 }, | |
1904 | |
1905 from : function (time, withoutSuffix) { | |
1906 return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix); | |
1907 }, | |
1908 | |
1909 fromNow : function (withoutSuffix) { | |
1910 return this.from(moment(), withoutSuffix); | |
1911 }, | |
1912 | |
1913 calendar : function () { | |
1914 // We want to compare the start of today, vs this. | |
1915 // Getting start-of-today depends on whether we're zone'd or not. | |
1916 var sod = makeAs(moment(), this).startOf('day'), | |
1917 diff = this.diff(sod, 'days', true), | |
1918 format = diff < -6 ? 'sameElse' : | |
1919 diff < -1 ? 'lastWeek' : | |
1920 diff < 0 ? 'lastDay' : | |
1921 diff < 1 ? 'sameDay' : | |
1922 diff < 2 ? 'nextDay' : | |
1923 diff < 7 ? 'nextWeek' : 'sameElse'; | |
1924 return this.format(this.lang().calendar(format, this)); | |
1925 }, | |
1926 | |
1927 isLeapYear : function () { | |
1928 return isLeapYear(this.year()); | |
1929 }, | |
1930 | |
1931 isDST : function () { | |
1932 return (this.zone() < this.clone().month(0).zone() || | |
1933 this.zone() < this.clone().month(5).zone()); | |
1934 }, | |
1935 | |
1936 day : function (input) { | |
1937 var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay(); | |
1938 if (input != null) { | |
1939 input = parseWeekday(input, this.lang()); | |
1940 return this.add({ d : input - day }); | |
1941 } else { | |
1942 return day; | |
1943 } | |
1944 }, | |
1945 | |
1946 month : function (input) { | |
1947 var utc = this._isUTC ? 'UTC' : '', | |
1948 dayOfMonth; | |
1949 | |
1950 if (input != null) { | |
1951 if (typeof input === 'string') { | |
1952 input = this.lang().monthsParse(input); | |
1953 if (typeof input !== 'number') { | |
1954 return this; | |
1955 } | |
1956 } | |
1957 | |
1958 dayOfMonth = this.date(); | |
1959 this.date(1); | |
1960 this._d['set' + utc + 'Month'](input); | |
1961 this.date(Math.min(dayOfMonth, this.daysInMonth())); | |
1962 | |
1963 moment.updateOffset(this); | |
1964 return this; | |
1965 } else { | |
1966 return this._d['get' + utc + 'Month'](); | |
1967 } | |
1968 }, | |
1969 | |
1970 startOf: function (units) { | |
1971 units = normalizeUnits(units); | |
1972 // the following switch intentionally omits break keywords | |
1973 // to utilize falling through the cases. | |
1974 switch (units) { | |
1975 case 'year': | |
1976 this.month(0); | |
1977 /* falls through */ | |
1978 case 'month': | |
1979 this.date(1); | |
1980 /* falls through */ | |
1981 case 'week': | |
1982 case 'isoWeek': | |
1983 case 'day': | |
1984 this.hours(0); | |
1985 /* falls through */ | |
1986 case 'hour': | |
1987 this.minutes(0); | |
1988 /* falls through */ | |
1989 case 'minute': | |
1990 this.seconds(0); | |
1991 /* falls through */ | |
1992 case 'second': | |
1993 this.milliseconds(0); | |
1994 /* falls through */ | |
1995 } | |
1996 | |
1997 // weeks are a special case | |
1998 if (units === 'week') { | |
1999 this.weekday(0); | |
2000 } else if (units === 'isoWeek') { | |
2001 this.isoWeekday(1); | |
2002 } | |
2003 | |
2004 return this; | |
2005 }, | |
2006 | |
2007 endOf: function (units) { | |
2008 units = normalizeUnits(units); | |
2009 return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1); | |
2010 }, | |
2011 | |
2012 isAfter: function (input, units) { | |
2013 units = typeof units !== 'undefined' ? units : 'millisecond'; | |
2014 return +this.clone().startOf(units) > +moment(input).startOf(units); | |
2015 }, | |
2016 | |
2017 isBefore: function (input, units) { | |
2018 units = typeof units !== 'undefined' ? units : 'millisecond'; | |
2019 return +this.clone().startOf(units) < +moment(input).startOf(units); | |
2020 }, | |
2021 | |
2022 isSame: function (input, units) { | |
2023 units = units || 'ms'; | |
2024 return +this.clone().startOf(units) === +makeAs(input, this).startOf(units); | |
2025 }, | |
2026 | |
2027 min: function (other) { | |
2028 other = moment.apply(null, arguments); | |
2029 return other < this ? this : other; | |
2030 }, | |
2031 | |
2032 max: function (other) { | |
2033 other = moment.apply(null, arguments); | |
2034 return other > this ? this : other; | |
2035 }, | |
2036 | |
2037 zone : function (input) { | |
2038 var offset = this._offset || 0; | |
2039 if (input != null) { | |
2040 if (typeof input === "string") { | |
2041 input = timezoneMinutesFromString(input); | |
2042 } | |
2043 if (Math.abs(input) < 16) { | |
2044 input = input * 60; | |
2045 } | |
2046 this._offset = input; | |
2047 this._isUTC = true; | |
2048 if (offset !== input) { | |
2049 addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true); | |
2050 } | |
2051 } else { | |
2052 return this._isUTC ? offset : this._d.getTimezoneOffset(); | |
2053 } | |
2054 return this; | |
2055 }, | |
2056 | |
2057 zoneAbbr : function () { | |
2058 return this._isUTC ? "UTC" : ""; | |
2059 }, | |
2060 | |
2061 zoneName : function () { | |
2062 return this._isUTC ? "Coordinated Universal Time" : ""; | |
2063 }, | |
2064 | |
2065 parseZone : function () { | |
2066 if (this._tzm) { | |
2067 this.zone(this._tzm); | |
2068 } else if (typeof this._i === 'string') { | |
2069 this.zone(this._i); | |
2070 } | |
2071 return this; | |
2072 }, | |
2073 | |
2074 hasAlignedHourOffset : function (input) { | |
2075 if (!input) { | |
2076 input = 0; | |
2077 } | |
2078 else { | |
2079 input = moment(input).zone(); | |
2080 } | |
2081 | |
2082 return (this.zone() - input) % 60 === 0; | |
2083 }, | |
2084 | |
2085 daysInMonth : function () { | |
2086 return daysInMonth(this.year(), this.month()); | |
2087 }, | |
2088 | |
2089 dayOfYear : function (input) { | |
2090 var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1; | |
2091 return input == null ? dayOfYear : this.add("d", (input - dayOfYear)); | |
2092 }, | |
2093 | |
2094 quarter : function () { | |
2095 return Math.ceil((this.month() + 1.0) / 3.0); | |
2096 }, | |
2097 | |
2098 weekYear : function (input) { | |
2099 var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year; | |
2100 return input == null ? year : this.add("y", (input - year)); | |
2101 }, | |
2102 | |
2103 isoWeekYear : function (input) { | |
2104 var year = weekOfYear(this, 1, 4).year; | |
2105 return input == null ? year : this.add("y", (input - year)); | |
2106 }, | |
2107 | |
2108 week : function (input) { | |
2109 var week = this.lang().week(this); | |
2110 return input == null ? week : this.add("d", (input - week) * 7); | |
2111 }, | |
2112 | |
2113 isoWeek : function (input) { | |
2114 var week = weekOfYear(this, 1, 4).week; | |
2115 return input == null ? week : this.add("d", (input - week) * 7); | |
2116 }, | |
2117 | |
2118 weekday : function (input) { | |
2119 var weekday = (this.day() + 7 - this.lang()._week.dow) % 7; | |
2120 return input == null ? weekday : this.add("d", input - weekday); | |
2121 }, | |
2122 | |
2123 isoWeekday : function (input) { | |
2124 // behaves the same as moment#day except | |
2125 // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6) | |
2126 // as a setter, sunday should belong to the previous week. | |
2127 return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7); | |
2128 }, | |
2129 | |
2130 get : function (units) { | |
2131 units = normalizeUnits(units); | |
2132 return this[units](); | |
2133 }, | |
2134 | |
2135 set : function (units, value) { | |
2136 units = normalizeUnits(units); | |
2137 if (typeof this[units] === 'function') { | |
2138 this[units](value); | |
2139 } | |
2140 return this; | |
2141 }, | |
2142 | |
2143 // If passed a language key, it will set the language for this | |
2144 // instance. Otherwise, it will return the language configuration | |
2145 // variables for this instance. | |
2146 lang : function (key) { | |
2147 if (key === undefined) { | |
2148 return this._lang; | |
2149 } else { | |
2150 this._lang = getLangDefinition(key); | |
2151 return this; | |
2152 } | |
2153 } | |
2154 }); | |
2155 | |
2156 // helper for adding shortcuts | |
2157 function makeGetterAndSetter(name, key) { | |
2158 moment.fn[name] = moment.fn[name + 's'] = function (input) { | |
2159 var utc = this._isUTC ? 'UTC' : ''; | |
2160 if (input != null) { | |
2161 this._d['set' + utc + key](input); | |
2162 moment.updateOffset(this); | |
2163 return this; | |
2164 } else { | |
2165 return this._d['get' + utc + key](); | |
2166 } | |
2167 }; | |
2168 } | |
2169 | |
2170 // loop through and add shortcuts (Month, Date, Hours, Minutes, Seconds, Milliseconds) | |
2171 for (i = 0; i < proxyGettersAndSetters.length; i ++) { | |
2172 makeGetterAndSetter(proxyGettersAndSetters[i].toLowerCase().replace(/s$/, ''), proxyGettersAndSetters[i]); | |
2173 } | |
2174 | |
2175 // add shortcut for year (uses different syntax than the getter/setter 'year' == 'FullYear') | |
2176 makeGetterAndSetter('year', 'FullYear'); | |
2177 | |
2178 // add plural methods | |
2179 moment.fn.days = moment.fn.day; | |
2180 moment.fn.months = moment.fn.month; | |
2181 moment.fn.weeks = moment.fn.week; | |
2182 moment.fn.isoWeeks = moment.fn.isoWeek; | |
2183 | |
2184 // add aliased format methods | |
2185 moment.fn.toJSON = moment.fn.toISOString; | |
2186 | |
2187 /************************************ | |
2188 Duration Prototype | |
2189 ************************************/ | |
2190 | |
2191 | |
2192 extend(moment.duration.fn = Duration.prototype, { | |
2193 | |
2194 _bubble : function () { | |
2195 var milliseconds = this._milliseconds, | |
2196 days = this._days, | |
2197 months = this._months, | |
2198 data = this._data, | |
2199 seconds, minutes, hours, years; | |
2200 | |
2201 // The following code bubbles up values, see the tests for | |
2202 // examples of what that means. | |
2203 data.milliseconds = milliseconds % 1000; | |
2204 | |
2205 seconds = absRound(milliseconds / 1000); | |
2206 data.seconds = seconds % 60; | |
2207 | |
2208 minutes = absRound(seconds / 60); | |
2209 data.minutes = minutes % 60; | |
2210 | |
2211 hours = absRound(minutes / 60); | |
2212 data.hours = hours % 24; | |
2213 | |
2214 days += absRound(hours / 24); | |
2215 data.days = days % 30; | |
2216 | |
2217 months += absRound(days / 30); | |
2218 data.months = months % 12; | |
2219 | |
2220 years = absRound(months / 12); | |
2221 data.years = years; | |
2222 }, | |
2223 | |
2224 weeks : function () { | |
2225 return absRound(this.days() / 7); | |
2226 }, | |
2227 | |
2228 valueOf : function () { | |
2229 return this._milliseconds + | |
2230 this._days * 864e5 + | |
2231 (this._months % 12) * 2592e6 + | |
2232 toInt(this._months / 12) * 31536e6; | |
2233 }, | |
2234 | |
2235 humanize : function (withSuffix) { | |
2236 var difference = +this, | |
2237 output = relativeTime(difference, !withSuffix, this.lang()); | |
2238 | |
2239 if (withSuffix) { | |
2240 output = this.lang().pastFuture(difference, output); | |
2241 } | |
2242 | |
2243 return this.lang().postformat(output); | |
2244 }, | |
2245 | |
2246 add : function (input, val) { | |
2247 // supports only 2.0-style add(1, 's') or add(moment) | |
2248 var dur = moment.duration(input, val); | |
2249 | |
2250 this._milliseconds += dur._milliseconds; | |
2251 this._days += dur._days; | |
2252 this._months += dur._months; | |
2253 | |
2254 this._bubble(); | |
2255 | |
2256 return this; | |
2257 }, | |
2258 | |
2259 subtract : function (input, val) { | |
2260 var dur = moment.duration(input, val); | |
2261 | |
2262 this._milliseconds -= dur._milliseconds; | |
2263 this._days -= dur._days; | |
2264 this._months -= dur._months; | |
2265 | |
2266 this._bubble(); | |
2267 | |
2268 return this; | |
2269 }, | |
2270 | |
2271 get : function (units) { | |
2272 units = normalizeUnits(units); | |
2273 return this[units.toLowerCase() + 's'](); | |
2274 }, | |
2275 | |
2276 as : function (units) { | |
2277 units = normalizeUnits(units); | |
2278 return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's'](); | |
2279 }, | |
2280 | |
2281 lang : moment.fn.lang, | |
2282 | |
2283 toIsoString : function () { | |
2284 // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js | |
2285 var years = Math.abs(this.years()), | |
2286 months = Math.abs(this.months()), | |
2287 days = Math.abs(this.days()), | |
2288 hours = Math.abs(this.hours()), | |
2289 minutes = Math.abs(this.minutes()), | |
2290 seconds = Math.abs(this.seconds() + this.milliseconds() / 1000); | |
2291 | |
2292 if (!this.asSeconds()) { | |
2293 // this is the same as C#'s (Noda) and python (isodate)... | |
2294 // but not other JS (goog.date) | |
2295 return 'P0D'; | |
2296 } | |
2297 | |
2298 return (this.asSeconds() < 0 ? '-' : '') + | |
2299 'P' + | |
2300 (years ? years + 'Y' : '') + | |
2301 (months ? months + 'M' : '') + | |
2302 (days ? days + 'D' : '') + | |
2303 ((hours || minutes || seconds) ? 'T' : '') + | |
2304 (hours ? hours + 'H' : '') + | |
2305 (minutes ? minutes + 'M' : '') + | |
2306 (seconds ? seconds + 'S' : ''); | |
2307 } | |
2308 }); | |
2309 | |
2310 function makeDurationGetter(name) { | |
2311 moment.duration.fn[name] = function () { | |
2312 return this._data[name]; | |
2313 }; | |
2314 } | |
2315 | |
2316 function makeDurationAsGetter(name, factor) { | |
2317 moment.duration.fn['as' + name] = function () { | |
2318 return +this / factor; | |
2319 }; | |
2320 } | |
2321 | |
2322 for (i in unitMillisecondFactors) { | |
2323 if (unitMillisecondFactors.hasOwnProperty(i)) { | |
2324 makeDurationAsGetter(i, unitMillisecondFactors[i]); | |
2325 makeDurationGetter(i.toLowerCase()); | |
2326 } | |
2327 } | |
2328 | |
2329 makeDurationAsGetter('Weeks', 6048e5); | |
2330 moment.duration.fn.asMonths = function () { | |
2331 return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12; | |
2332 }; | |
2333 | |
2334 | |
2335 /************************************ | |
2336 Default Lang | |
2337 ************************************/ | |
2338 | |
2339 | |
2340 // Set default language, other languages will inherit from English. | |
2341 moment.lang('en', { | |
2342 ordinal : function (number) { | |
2343 var b = number % 10, | |
2344 output = (toInt(number % 100 / 10) === 1) ? 'th' : | |
2345 (b === 1) ? 'st' : | |
2346 (b === 2) ? 'nd' : | |
2347 (b === 3) ? 'rd' : 'th'; | |
2348 return number + output; | |
2349 } | |
2350 }); | |
2351 | |
2352 /* EMBED_LANGUAGES */ | |
2353 | |
2354 /************************************ | |
2355 Exposing Moment | |
2356 ************************************/ | |
2357 | |
2358 function makeGlobal(deprecate) { | |
2359 var warned = false, local_moment = moment; | |
2360 /*global ender:false */ | |
2361 if (typeof ender !== 'undefined') { | |
2362 return; | |
2363 } | |
2364 // here, `this` means `window` in the browser, or `global` on the server | |
2365 // add `moment` as a global object via a string identifier, | |
2366 // for Closure Compiler "advanced" mode | |
2367 if (deprecate) { | |
2368 global.moment = function () { | |
2369 if (!warned && console && console.warn) { | |
2370 warned = true; | |
2371 console.warn( | |
2372 "Accessing Moment through the global scope is " + | |
2373 "deprecated, and will be removed in an upcoming " + | |
2374 "release."); | |
2375 } | |
2376 return local_moment.apply(null, arguments); | |
2377 }; | |
2378 extend(global.moment, local_moment); | |
2379 } else { | |
2380 global['moment'] = moment; | |
2381 } | |
2382 } | |
2383 | |
2384 // CommonJS module is defined | |
2385 if (hasModule) { | |
2386 module.exports = moment; | |
2387 makeGlobal(true); | |
2388 } else if (typeof define === "function" && define.amd) { | |
2389 define("moment", function (require, exports, module) { | |
2390 if (module.config && module.config() && module.config().noGlobal !== true) { | |
2391 // If user provided noGlobal, he is aware of global | |
2392 makeGlobal(module.config().noGlobal === undefined); | |
2393 } | |
2394 | |
2395 return moment; | |
2396 }); | |
2397 } else { | |
2398 makeGlobal(); | |
2399 } | |
2400 }).call(this); |