blazer 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of blazer might be problematic. Click here for more details.

@@ -1,19 +1,21 @@
1
1
  //! moment.js
2
- //! version : 2.5.1
2
+ //! version : 2.9.0
3
3
  //! authors : Tim Wood, Iskren Chernev, Moment.js contributors
4
4
  //! license : MIT
5
5
  //! momentjs.com
6
6
 
7
7
  (function (undefined) {
8
-
9
8
  /************************************
10
9
  Constants
11
10
  ************************************/
12
11
 
13
12
  var moment,
14
- VERSION = "2.5.1",
15
- global = this,
13
+ VERSION = '2.9.0',
14
+ // the global-scope this is NOT the global object in Node.js
15
+ globalScope = (typeof global !== 'undefined' && (typeof window === 'undefined' || window === global.window)) ? global : this,
16
+ oldGlobalMoment,
16
17
  round = Math.round,
18
+ hasOwnProperty = Object.prototype.hasOwnProperty,
17
19
  i,
18
20
 
19
21
  YEAR = 0,
@@ -24,24 +26,14 @@
24
26
  SECOND = 5,
25
27
  MILLISECOND = 6,
26
28
 
27
- // internal storage for language config files
28
- languages = {},
29
+ // internal storage for locale config files
30
+ locales = {},
29
31
 
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
- },
32
+ // extra moment internal properties (plugins register props here)
33
+ momentProperties = [],
42
34
 
43
35
  // check for nodeJS
44
- hasModule = (typeof module !== 'undefined' && module.exports && typeof require !== 'undefined'),
36
+ hasModule = (typeof module !== 'undefined' && module && module.exports),
45
37
 
46
38
  // ASP.NET json date format regex
47
39
  aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
@@ -52,8 +44,8 @@
52
44
  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
45
 
54
46
  // 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,
47
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Q|YYYYYY|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|S{1,4}|x|X|zz?|ZZ?|.)/g,
48
+ localFormattingTokens = /(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,
57
49
 
58
50
  // parsing token regexes
59
51
  parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
@@ -64,6 +56,7 @@
64
56
  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
57
  parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/gi, // +00:00 -00:00 +0000 -0000 or Z
66
58
  parseTokenT = /T/i, // T (ISO separator)
59
+ parseTokenOffsetMs = /[\+\-]?\d+/, // 1234567890123
67
60
  parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
68
61
 
69
62
  //strict parsing regexes
@@ -90,13 +83,13 @@
90
83
 
91
84
  // iso time formats and regexes
92
85
  isoTimes = [
93
- ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d{1,3}/],
86
+ ['HH:mm:ss.SSSS', /(T| )\d\d:\d\d:\d\d\.\d+/],
94
87
  ['HH:mm:ss', /(T| )\d\d:\d\d:\d\d/],
95
88
  ['HH:mm', /(T| )\d\d:\d\d/],
96
89
  ['HH', /(T| )\d\d/]
97
90
  ],
98
91
 
99
- // timezone chunker "+10:00" > ["10", "00"] or "-1530" > ["-15", "30"]
92
+ // timezone chunker '+10:00' > ['10', '00'] or '-1530' > ['-', '15', '30']
100
93
  parseTimezoneChunker = /([\+\-]|\d\d)/gi,
101
94
 
102
95
  // getter and setter names
@@ -121,6 +114,7 @@
121
114
  w : 'week',
122
115
  W : 'isoWeek',
123
116
  M : 'month',
117
+ Q : 'quarter',
124
118
  y : 'year',
125
119
  DDD : 'dayOfYear',
126
120
  e : 'weekday',
@@ -140,6 +134,15 @@
140
134
  // format function strings
141
135
  formatFunctions = {},
142
136
 
137
+ // default relative time thresholds
138
+ relativeTimeThresholds = {
139
+ s: 45, // seconds to minute
140
+ m: 45, // minutes to hour
141
+ h: 22, // hours to day
142
+ d: 26, // days to month
143
+ M: 11 // months to year
144
+ },
145
+
143
146
  // tokens to ordinalize and pad
144
147
  ordinalizeTokens = 'DDD w W M D d'.split(' '),
145
148
  paddedTokens = 'M D H h m s w W'.split(' '),
@@ -149,10 +152,10 @@
149
152
  return this.month() + 1;
150
153
  },
151
154
  MMM : function (format) {
152
- return this.lang().monthsShort(this, format);
155
+ return this.localeData().monthsShort(this, format);
153
156
  },
154
157
  MMMM : function (format) {
155
- return this.lang().months(this, format);
158
+ return this.localeData().months(this, format);
156
159
  },
157
160
  D : function () {
158
161
  return this.date();
@@ -164,13 +167,13 @@
164
167
  return this.day();
165
168
  },
166
169
  dd : function (format) {
167
- return this.lang().weekdaysMin(this, format);
170
+ return this.localeData().weekdaysMin(this, format);
168
171
  },
169
172
  ddd : function (format) {
170
- return this.lang().weekdaysShort(this, format);
173
+ return this.localeData().weekdaysShort(this, format);
171
174
  },
172
175
  dddd : function (format) {
173
- return this.lang().weekdays(this, format);
176
+ return this.localeData().weekdays(this, format);
174
177
  },
175
178
  w : function () {
176
179
  return this.week();
@@ -216,10 +219,10 @@
216
219
  return this.isoWeekday();
217
220
  },
218
221
  a : function () {
219
- return this.lang().meridiem(this.hours(), this.minutes(), true);
222
+ return this.localeData().meridiem(this.hours(), this.minutes(), true);
220
223
  },
221
224
  A : function () {
222
- return this.lang().meridiem(this.hours(), this.minutes(), false);
225
+ return this.localeData().meridiem(this.hours(), this.minutes(), false);
223
226
  },
224
227
  H : function () {
225
228
  return this.hours();
@@ -246,20 +249,20 @@
246
249
  return leftZeroFill(this.milliseconds(), 3);
247
250
  },
248
251
  Z : function () {
249
- var a = -this.zone(),
250
- b = "+";
252
+ var a = this.utcOffset(),
253
+ b = '+';
251
254
  if (a < 0) {
252
255
  a = -a;
253
- b = "-";
256
+ b = '-';
254
257
  }
255
- return b + leftZeroFill(toInt(a / 60), 2) + ":" + leftZeroFill(toInt(a) % 60, 2);
258
+ return b + leftZeroFill(toInt(a / 60), 2) + ':' + leftZeroFill(toInt(a) % 60, 2);
256
259
  },
257
260
  ZZ : function () {
258
- var a = -this.zone(),
259
- b = "+";
261
+ var a = this.utcOffset(),
262
+ b = '+';
260
263
  if (a < 0) {
261
264
  a = -a;
262
- b = "-";
265
+ b = '-';
263
266
  }
264
267
  return b + leftZeroFill(toInt(a / 60), 2) + leftZeroFill(toInt(a) % 60, 2);
265
268
  },
@@ -269,6 +272,9 @@
269
272
  zz : function () {
270
273
  return this.zoneName();
271
274
  },
275
+ x : function () {
276
+ return this.valueOf();
277
+ },
272
278
  X : function () {
273
279
  return this.unix();
274
280
  },
@@ -277,7 +283,25 @@
277
283
  }
278
284
  },
279
285
 
280
- lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'];
286
+ deprecations = {},
287
+
288
+ lists = ['months', 'monthsShort', 'weekdays', 'weekdaysShort', 'weekdaysMin'],
289
+
290
+ updateInProgress = false;
291
+
292
+ // Pick the first defined of two or three arguments. dfl comes from
293
+ // default.
294
+ function dfl(a, b, c) {
295
+ switch (arguments.length) {
296
+ case 2: return a != null ? a : b;
297
+ case 3: return a != null ? a : b != null ? b : c;
298
+ default: throw new Error('Implement me');
299
+ }
300
+ }
301
+
302
+ function hasOwnProp(a, b) {
303
+ return hasOwnProperty.call(a, b);
304
+ }
281
305
 
282
306
  function defaultParsingFlags() {
283
307
  // We need to deep clone this object, and es5 standard is not very
@@ -296,6 +320,31 @@
296
320
  };
297
321
  }
298
322
 
323
+ function printMsg(msg) {
324
+ if (moment.suppressDeprecationWarnings === false &&
325
+ typeof console !== 'undefined' && console.warn) {
326
+ console.warn('Deprecation warning: ' + msg);
327
+ }
328
+ }
329
+
330
+ function deprecate(msg, fn) {
331
+ var firstTime = true;
332
+ return extend(function () {
333
+ if (firstTime) {
334
+ printMsg(msg);
335
+ firstTime = false;
336
+ }
337
+ return fn.apply(this, arguments);
338
+ }, fn);
339
+ }
340
+
341
+ function deprecateSimple(name, msg) {
342
+ if (!deprecations[name]) {
343
+ printMsg(msg);
344
+ deprecations[name] = true;
345
+ }
346
+ }
347
+
299
348
  function padToken(func, count) {
300
349
  return function (a) {
301
350
  return leftZeroFill(func.call(this, a), count);
@@ -303,10 +352,30 @@
303
352
  }
304
353
  function ordinalizeToken(func, period) {
305
354
  return function (a) {
306
- return this.lang().ordinal(func.call(this, a), period);
355
+ return this.localeData().ordinal(func.call(this, a), period);
307
356
  };
308
357
  }
309
358
 
359
+ function monthDiff(a, b) {
360
+ // difference in months
361
+ var wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()),
362
+ // b is in (anchor - 1 month, anchor + 1 month)
363
+ anchor = a.clone().add(wholeMonthDiff, 'months'),
364
+ anchor2, adjust;
365
+
366
+ if (b - anchor < 0) {
367
+ anchor2 = a.clone().add(wholeMonthDiff - 1, 'months');
368
+ // linear across the month
369
+ adjust = (b - anchor) / (anchor - anchor2);
370
+ } else {
371
+ anchor2 = a.clone().add(wholeMonthDiff + 1, 'months');
372
+ // linear across the month
373
+ adjust = (b - anchor) / (anchor2 - anchor);
374
+ }
375
+
376
+ return -(wholeMonthDiff + adjust);
377
+ }
378
+
310
379
  while (ordinalizeTokens.length) {
311
380
  i = ordinalizeTokens.pop();
312
381
  formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
@@ -318,24 +387,59 @@
318
387
  formatTokenFunctions.DDDD = padToken(formatTokenFunctions.DDD, 3);
319
388
 
320
389
 
390
+ function meridiemFixWrap(locale, hour, meridiem) {
391
+ var isPm;
392
+
393
+ if (meridiem == null) {
394
+ // nothing to do
395
+ return hour;
396
+ }
397
+ if (locale.meridiemHour != null) {
398
+ return locale.meridiemHour(hour, meridiem);
399
+ } else if (locale.isPM != null) {
400
+ // Fallback
401
+ isPm = locale.isPM(meridiem);
402
+ if (isPm && hour < 12) {
403
+ hour += 12;
404
+ }
405
+ if (!isPm && hour === 12) {
406
+ hour = 0;
407
+ }
408
+ return hour;
409
+ } else {
410
+ // thie is not supposed to happen
411
+ return hour;
412
+ }
413
+ }
414
+
321
415
  /************************************
322
416
  Constructors
323
417
  ************************************/
324
418
 
325
- function Language() {
326
-
419
+ function Locale() {
327
420
  }
328
421
 
329
422
  // Moment prototype object
330
- function Moment(config) {
331
- checkOverflow(config);
332
- extend(this, config);
423
+ function Moment(config, skipOverflow) {
424
+ if (skipOverflow !== false) {
425
+ checkOverflow(config);
426
+ }
427
+ copyConfig(this, config);
428
+ this._d = new Date(+config._d);
429
+ // Prevent infinite loop in case updateOffset creates new moment
430
+ // objects.
431
+ if (updateInProgress === false) {
432
+ updateInProgress = true;
433
+ moment.updateOffset(this);
434
+ updateInProgress = false;
435
+ }
333
436
  }
334
437
 
335
438
  // Duration Constructor
336
439
  function Duration(duration) {
337
440
  var normalizedInput = normalizeObjectUnits(duration),
338
441
  years = normalizedInput.year || 0,
442
+ quarters = normalizedInput.quarter || 0,
339
443
  months = normalizedInput.month || 0,
340
444
  weeks = normalizedInput.week || 0,
341
445
  days = normalizedInput.day || 0,
@@ -357,10 +461,13 @@
357
461
  // which months you are are talking about, so we have to store
358
462
  // it separately.
359
463
  this._months = +months +
464
+ quarters * 3 +
360
465
  years * 12;
361
466
 
362
467
  this._data = {};
363
468
 
469
+ this._locale = moment.localeData();
470
+
364
471
  this._bubble();
365
472
  }
366
473
 
@@ -371,31 +478,67 @@
371
478
 
372
479
  function extend(a, b) {
373
480
  for (var i in b) {
374
- if (b.hasOwnProperty(i)) {
481
+ if (hasOwnProp(b, i)) {
375
482
  a[i] = b[i];
376
483
  }
377
484
  }
378
485
 
379
- if (b.hasOwnProperty("toString")) {
486
+ if (hasOwnProp(b, 'toString')) {
380
487
  a.toString = b.toString;
381
488
  }
382
489
 
383
- if (b.hasOwnProperty("valueOf")) {
490
+ if (hasOwnProp(b, 'valueOf')) {
384
491
  a.valueOf = b.valueOf;
385
492
  }
386
493
 
387
494
  return a;
388
495
  }
389
496
 
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];
497
+ function copyConfig(to, from) {
498
+ var i, prop, val;
499
+
500
+ if (typeof from._isAMomentObject !== 'undefined') {
501
+ to._isAMomentObject = from._isAMomentObject;
502
+ }
503
+ if (typeof from._i !== 'undefined') {
504
+ to._i = from._i;
505
+ }
506
+ if (typeof from._f !== 'undefined') {
507
+ to._f = from._f;
508
+ }
509
+ if (typeof from._l !== 'undefined') {
510
+ to._l = from._l;
511
+ }
512
+ if (typeof from._strict !== 'undefined') {
513
+ to._strict = from._strict;
514
+ }
515
+ if (typeof from._tzm !== 'undefined') {
516
+ to._tzm = from._tzm;
517
+ }
518
+ if (typeof from._isUTC !== 'undefined') {
519
+ to._isUTC = from._isUTC;
520
+ }
521
+ if (typeof from._offset !== 'undefined') {
522
+ to._offset = from._offset;
523
+ }
524
+ if (typeof from._pf !== 'undefined') {
525
+ to._pf = from._pf;
526
+ }
527
+ if (typeof from._locale !== 'undefined') {
528
+ to._locale = from._locale;
529
+ }
530
+
531
+ if (momentProperties.length > 0) {
532
+ for (i in momentProperties) {
533
+ prop = momentProperties[i];
534
+ val = from[prop];
535
+ if (typeof val !== 'undefined') {
536
+ to[prop] = val;
537
+ }
395
538
  }
396
539
  }
397
540
 
398
- return result;
541
+ return to;
399
542
  }
400
543
 
401
544
  function absRound(number) {
@@ -418,35 +561,68 @@
418
561
  return (sign ? (forceSign ? '+' : '') : '-') + output;
419
562
  }
420
563
 
421
- // helper function for _.addTime and _.subtractTime
422
- function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
564
+ function positiveMomentsDifference(base, other) {
565
+ var res = {milliseconds: 0, months: 0};
566
+
567
+ res.months = other.month() - base.month() +
568
+ (other.year() - base.year()) * 12;
569
+ if (base.clone().add(res.months, 'M').isAfter(other)) {
570
+ --res.months;
571
+ }
572
+
573
+ res.milliseconds = +other - +(base.clone().add(res.months, 'M'));
574
+
575
+ return res;
576
+ }
577
+
578
+ function momentsDifference(base, other) {
579
+ var res;
580
+ other = makeAs(other, base);
581
+ if (base.isBefore(other)) {
582
+ res = positiveMomentsDifference(base, other);
583
+ } else {
584
+ res = positiveMomentsDifference(other, base);
585
+ res.milliseconds = -res.milliseconds;
586
+ res.months = -res.months;
587
+ }
588
+
589
+ return res;
590
+ }
591
+
592
+ // TODO: remove 'name' arg after deprecation is removed
593
+ function createAdder(direction, name) {
594
+ return function (val, period) {
595
+ var dur, tmp;
596
+ //invert the arguments, but complain about it
597
+ if (period !== null && !isNaN(+period)) {
598
+ deprecateSimple(name, 'moment().' + name + '(period, number) is deprecated. Please use moment().' + name + '(number, period).');
599
+ tmp = val; val = period; period = tmp;
600
+ }
601
+
602
+ val = typeof val === 'string' ? +val : val;
603
+ dur = moment.duration(val, period);
604
+ addOrSubtractDurationFromMoment(this, dur, direction);
605
+ return this;
606
+ };
607
+ }
608
+
609
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding, updateOffset) {
423
610
  var milliseconds = duration._milliseconds,
424
611
  days = duration._days,
425
- months = duration._months,
426
- minutes,
427
- hours;
612
+ months = duration._months;
613
+ updateOffset = updateOffset == null ? true : updateOffset;
428
614
 
429
615
  if (milliseconds) {
430
616
  mom._d.setTime(+mom._d + milliseconds * isAdding);
431
617
  }
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
618
  if (days) {
438
- mom.date(mom.date() + days * isAdding);
619
+ rawSetter(mom, 'Date', rawGetter(mom, 'Date') + days * isAdding);
439
620
  }
440
621
  if (months) {
441
- mom.month(mom.month() + months * isAdding);
442
- }
443
- if (milliseconds && !ignoreUpdateOffset) {
444
- moment.updateOffset(mom);
622
+ rawMonthSetter(mom, rawGetter(mom, 'Month') + months * isAdding);
445
623
  }
446
- // restore the minutes and hours after possibly changing dst
447
- if (days || months) {
448
- mom.minute(minutes);
449
- mom.hour(hours);
624
+ if (updateOffset) {
625
+ moment.updateOffset(mom, days || months);
450
626
  }
451
627
  }
452
628
 
@@ -456,8 +632,8 @@
456
632
  }
457
633
 
458
634
  function isDate(input) {
459
- return Object.prototype.toString.call(input) === '[object Date]' ||
460
- input instanceof Date;
635
+ return Object.prototype.toString.call(input) === '[object Date]' ||
636
+ input instanceof Date;
461
637
  }
462
638
 
463
639
  // compare two arrays, return the number of differences
@@ -489,7 +665,7 @@
489
665
  prop;
490
666
 
491
667
  for (prop in inputObject) {
492
- if (inputObject.hasOwnProperty(prop)) {
668
+ if (hasOwnProp(inputObject, prop)) {
493
669
  normalizedProp = normalizeUnits(prop);
494
670
  if (normalizedProp) {
495
671
  normalizedInput[normalizedProp] = inputObject[prop];
@@ -517,7 +693,7 @@
517
693
 
518
694
  moment[field] = function (format, index) {
519
695
  var i, getter,
520
- method = moment.fn._lang[field],
696
+ method = moment._locale[field],
521
697
  results = [];
522
698
 
523
699
  if (typeof format === 'number') {
@@ -527,7 +703,7 @@
527
703
 
528
704
  getter = function (i) {
529
705
  var m = moment().utc().set(setter, i);
530
- return method.call(moment.fn._lang, m, format || '');
706
+ return method.call(moment._locale, m, format || '');
531
707
  };
532
708
 
533
709
  if (index != null) {
@@ -561,6 +737,10 @@
561
737
  return new Date(Date.UTC(year, month + 1, 0)).getUTCDate();
562
738
  }
563
739
 
740
+ function weeksInYear(year, dow, doy) {
741
+ return weekOfYear(moment([year, 11, 31 + dow - doy]), dow, doy).week;
742
+ }
743
+
564
744
  function daysInYear(year) {
565
745
  return isLeapYear(year) ? 366 : 365;
566
746
  }
@@ -575,7 +755,10 @@
575
755
  overflow =
576
756
  m._a[MONTH] < 0 || m._a[MONTH] > 11 ? MONTH :
577
757
  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 :
758
+ m._a[HOUR] < 0 || m._a[HOUR] > 24 ||
759
+ (m._a[HOUR] === 24 && (m._a[MINUTE] !== 0 ||
760
+ m._a[SECOND] !== 0 ||
761
+ m._a[MILLISECOND] !== 0)) ? HOUR :
579
762
  m._a[MINUTE] < 0 || m._a[MINUTE] > 59 ? MINUTE :
580
763
  m._a[SECOND] < 0 || m._a[SECOND] > 59 ? SECOND :
581
764
  m._a[MILLISECOND] < 0 || m._a[MILLISECOND] > 999 ? MILLISECOND :
@@ -602,28 +785,80 @@
602
785
  if (m._strict) {
603
786
  m._isValid = m._isValid &&
604
787
  m._pf.charsLeftOver === 0 &&
605
- m._pf.unusedTokens.length === 0;
788
+ m._pf.unusedTokens.length === 0 &&
789
+ m._pf.bigHour === undefined;
606
790
  }
607
791
  }
608
792
  return m._isValid;
609
793
  }
610
794
 
611
- function normalizeLanguage(key) {
795
+ function normalizeLocale(key) {
612
796
  return key ? key.toLowerCase().replace('_', '-') : key;
613
797
  }
614
798
 
615
- // Return a moment from input, that is local/utc/zone equivalent to model.
799
+ // pick the locale from the array
800
+ // try ['en-au', 'en-gb'] as 'en-au', 'en-gb', 'en', as in move through the list trying each
801
+ // substring from most specific to least, but move to the next array item if it's a more specific variant than the current root
802
+ function chooseLocale(names) {
803
+ var i = 0, j, next, locale, split;
804
+
805
+ while (i < names.length) {
806
+ split = normalizeLocale(names[i]).split('-');
807
+ j = split.length;
808
+ next = normalizeLocale(names[i + 1]);
809
+ next = next ? next.split('-') : null;
810
+ while (j > 0) {
811
+ locale = loadLocale(split.slice(0, j).join('-'));
812
+ if (locale) {
813
+ return locale;
814
+ }
815
+ if (next && next.length >= j && compareArrays(split, next, true) >= j - 1) {
816
+ //the next array item is better than a shallower substring of this one
817
+ break;
818
+ }
819
+ j--;
820
+ }
821
+ i++;
822
+ }
823
+ return null;
824
+ }
825
+
826
+ function loadLocale(name) {
827
+ var oldLocale = null;
828
+ if (!locales[name] && hasModule) {
829
+ try {
830
+ oldLocale = moment.locale();
831
+ require('./locale/' + name);
832
+ // because defineLocale currently also sets the global locale, we want to undo that for lazy loaded locales
833
+ moment.locale(oldLocale);
834
+ } catch (e) { }
835
+ }
836
+ return locales[name];
837
+ }
838
+
839
+ // Return a moment from input, that is local/utc/utcOffset equivalent to
840
+ // model.
616
841
  function makeAs(input, model) {
617
- return model._isUTC ? moment(input).zone(model._offset || 0) :
618
- moment(input).local();
842
+ var res, diff;
843
+ if (model._isUTC) {
844
+ res = model.clone();
845
+ diff = (moment.isMoment(input) || isDate(input) ?
846
+ +input : +moment(input)) - (+res);
847
+ // Use low-level api, because this fn is low-level api.
848
+ res._d.setTime(+res._d + diff);
849
+ moment.updateOffset(res, false);
850
+ return res;
851
+ } else {
852
+ return moment(input).local();
853
+ }
619
854
  }
620
855
 
621
856
  /************************************
622
- Languages
857
+ Locale
623
858
  ************************************/
624
859
 
625
860
 
626
- extend(Language.prototype, {
861
+ extend(Locale.prototype, {
627
862
 
628
863
  set : function (config) {
629
864
  var prop, i;
@@ -635,50 +870,63 @@
635
870
  this['_' + i] = prop;
636
871
  }
637
872
  }
873
+ // Lenient ordinal parsing accepts just a number in addition to
874
+ // number + (possibly) stuff coming from _ordinalParseLenient.
875
+ this._ordinalParseLenient = new RegExp(this._ordinalParse.source + '|' + /\d{1,2}/.source);
638
876
  },
639
877
 
640
- _months : "January_February_March_April_May_June_July_August_September_October_November_December".split("_"),
878
+ _months : 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
641
879
  months : function (m) {
642
880
  return this._months[m.month()];
643
881
  },
644
882
 
645
- _monthsShort : "Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),
883
+ _monthsShort : 'Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec'.split('_'),
646
884
  monthsShort : function (m) {
647
885
  return this._monthsShort[m.month()];
648
886
  },
649
887
 
650
- monthsParse : function (monthName) {
888
+ monthsParse : function (monthName, format, strict) {
651
889
  var i, mom, regex;
652
890
 
653
891
  if (!this._monthsParse) {
654
892
  this._monthsParse = [];
893
+ this._longMonthsParse = [];
894
+ this._shortMonthsParse = [];
655
895
  }
656
896
 
657
897
  for (i = 0; i < 12; i++) {
658
898
  // make the regex if we don't have it already
659
- if (!this._monthsParse[i]) {
660
- mom = moment.utc([2000, i]);
899
+ mom = moment.utc([2000, i]);
900
+ if (strict && !this._longMonthsParse[i]) {
901
+ this._longMonthsParse[i] = new RegExp('^' + this.months(mom, '').replace('.', '') + '$', 'i');
902
+ this._shortMonthsParse[i] = new RegExp('^' + this.monthsShort(mom, '').replace('.', '') + '$', 'i');
903
+ }
904
+ if (!strict && !this._monthsParse[i]) {
661
905
  regex = '^' + this.months(mom, '') + '|^' + this.monthsShort(mom, '');
662
906
  this._monthsParse[i] = new RegExp(regex.replace('.', ''), 'i');
663
907
  }
664
908
  // test the regex
665
- if (this._monthsParse[i].test(monthName)) {
909
+ if (strict && format === 'MMMM' && this._longMonthsParse[i].test(monthName)) {
910
+ return i;
911
+ } else if (strict && format === 'MMM' && this._shortMonthsParse[i].test(monthName)) {
912
+ return i;
913
+ } else if (!strict && this._monthsParse[i].test(monthName)) {
666
914
  return i;
667
915
  }
668
916
  }
669
917
  },
670
918
 
671
- _weekdays : "Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),
919
+ _weekdays : 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
672
920
  weekdays : function (m) {
673
921
  return this._weekdays[m.day()];
674
922
  },
675
923
 
676
- _weekdaysShort : "Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),
924
+ _weekdaysShort : 'Sun_Mon_Tue_Wed_Thu_Fri_Sat'.split('_'),
677
925
  weekdaysShort : function (m) {
678
926
  return this._weekdaysShort[m.day()];
679
927
  },
680
928
 
681
- _weekdaysMin : "Su_Mo_Tu_We_Th_Fr_Sa".split("_"),
929
+ _weekdaysMin : 'Su_Mo_Tu_We_Th_Fr_Sa'.split('_'),
682
930
  weekdaysMin : function (m) {
683
931
  return this._weekdaysMin[m.day()];
684
932
  },
@@ -705,11 +953,12 @@
705
953
  },
706
954
 
707
955
  _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"
956
+ LTS : 'h:mm:ss A',
957
+ LT : 'h:mm A',
958
+ L : 'MM/DD/YYYY',
959
+ LL : 'MMMM D, YYYY',
960
+ LLL : 'MMMM D, YYYY LT',
961
+ LLLL : 'dddd, MMMM D, YYYY LT'
713
962
  },
714
963
  longDateFormat : function (key) {
715
964
  var output = this._longDateFormat[key];
@@ -737,6 +986,7 @@
737
986
  }
738
987
  },
739
988
 
989
+
740
990
  _calendar : {
741
991
  sameDay : '[Today at] LT',
742
992
  nextDay : '[Tomorrow at] LT',
@@ -745,41 +995,44 @@
745
995
  lastWeek : '[Last] dddd [at] LT',
746
996
  sameElse : 'L'
747
997
  },
748
- calendar : function (key, mom) {
998
+ calendar : function (key, mom, now) {
749
999
  var output = this._calendar[key];
750
- return typeof output === 'function' ? output.apply(mom) : output;
1000
+ return typeof output === 'function' ? output.apply(mom, [now]) : output;
751
1001
  },
752
1002
 
753
1003
  _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"
1004
+ future : 'in %s',
1005
+ past : '%s ago',
1006
+ s : 'a few seconds',
1007
+ m : 'a minute',
1008
+ mm : '%d minutes',
1009
+ h : 'an hour',
1010
+ hh : '%d hours',
1011
+ d : 'a day',
1012
+ dd : '%d days',
1013
+ M : 'a month',
1014
+ MM : '%d months',
1015
+ y : 'a year',
1016
+ yy : '%d years'
767
1017
  },
1018
+
768
1019
  relativeTime : function (number, withoutSuffix, string, isFuture) {
769
1020
  var output = this._relativeTime[string];
770
1021
  return (typeof output === 'function') ?
771
1022
  output(number, withoutSuffix, string, isFuture) :
772
1023
  output.replace(/%d/i, number);
773
1024
  },
1025
+
774
1026
  pastFuture : function (diff, output) {
775
1027
  var format = this._relativeTime[diff > 0 ? 'future' : 'past'];
776
1028
  return typeof format === 'function' ? format(output) : format.replace(/%s/i, output);
777
1029
  },
778
1030
 
779
1031
  ordinal : function (number) {
780
- return this._ordinal.replace("%d", number);
1032
+ return this._ordinal.replace('%d', number);
781
1033
  },
782
- _ordinal : "%d",
1034
+ _ordinal : '%d',
1035
+ _ordinalParse : /\d{1,2}/,
783
1036
 
784
1037
  preparse : function (string) {
785
1038
  return string;
@@ -798,84 +1051,20 @@
798
1051
  doy : 6 // The week that contains Jan 1st is the first week of the year.
799
1052
  },
800
1053
 
1054
+ firstDayOfWeek : function () {
1055
+ return this._week.dow;
1056
+ },
1057
+
1058
+ firstDayOfYear : function () {
1059
+ return this._week.doy;
1060
+ },
1061
+
801
1062
  _invalidDate: 'Invalid date',
802
1063
  invalidDate: function () {
803
1064
  return this._invalidDate;
804
1065
  }
805
1066
  });
806
1067
 
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
1068
  /************************************
880
1069
  Formatting
881
1070
  ************************************/
@@ -883,9 +1072,9 @@
883
1072
 
884
1073
  function removeFormattingTokens(input) {
885
1074
  if (input.match(/\[[\s\S]/)) {
886
- return input.replace(/^\[|\]$/g, "");
1075
+ return input.replace(/^\[|\]$/g, '');
887
1076
  }
888
- return input.replace(/\\/g, "");
1077
+ return input.replace(/\\/g, '');
889
1078
  }
890
1079
 
891
1080
  function makeFormatFunction(format) {
@@ -900,7 +1089,7 @@
900
1089
  }
901
1090
 
902
1091
  return function (mom) {
903
- var output = "";
1092
+ var output = '';
904
1093
  for (i = 0; i < length; i++) {
905
1094
  output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
906
1095
  }
@@ -910,12 +1099,11 @@
910
1099
 
911
1100
  // format date using native date object
912
1101
  function formatMoment(m, format) {
913
-
914
1102
  if (!m.isValid()) {
915
- return m.lang().invalidDate();
1103
+ return m.localeData().invalidDate();
916
1104
  }
917
1105
 
918
- format = expandFormat(format, m.lang());
1106
+ format = expandFormat(format, m.localeData());
919
1107
 
920
1108
  if (!formatFunctions[format]) {
921
1109
  formatFunctions[format] = makeFormatFunction(format);
@@ -924,11 +1112,11 @@
924
1112
  return formatFunctions[format](m);
925
1113
  }
926
1114
 
927
- function expandFormat(format, lang) {
1115
+ function expandFormat(format, locale) {
928
1116
  var i = 5;
929
1117
 
930
1118
  function replaceLongDateFormatTokens(input) {
931
- return lang.longDateFormat(input) || input;
1119
+ return locale.longDateFormat(input) || input;
932
1120
  }
933
1121
 
934
1122
  localFormattingTokens.lastIndex = 0;
@@ -951,6 +1139,8 @@
951
1139
  function getParseRegexForToken(token, config) {
952
1140
  var a, strict = config._strict;
953
1141
  switch (token) {
1142
+ case 'Q':
1143
+ return parseTokenOneDigit;
954
1144
  case 'DDDD':
955
1145
  return parseTokenThreeDigits;
956
1146
  case 'YYYY':
@@ -967,13 +1157,19 @@
967
1157
  case 'ggggg':
968
1158
  return strict ? parseTokenSixDigits : parseTokenOneToSixDigits;
969
1159
  case 'S':
970
- if (strict) { return parseTokenOneDigit; }
1160
+ if (strict) {
1161
+ return parseTokenOneDigit;
1162
+ }
971
1163
  /* falls through */
972
1164
  case 'SS':
973
- if (strict) { return parseTokenTwoDigits; }
1165
+ if (strict) {
1166
+ return parseTokenTwoDigits;
1167
+ }
974
1168
  /* falls through */
975
1169
  case 'SSS':
976
- if (strict) { return parseTokenThreeDigits; }
1170
+ if (strict) {
1171
+ return parseTokenThreeDigits;
1172
+ }
977
1173
  /* falls through */
978
1174
  case 'DDD':
979
1175
  return parseTokenOneToThreeDigits;
@@ -985,7 +1181,9 @@
985
1181
  return parseTokenWord;
986
1182
  case 'a':
987
1183
  case 'A':
988
- return getLangDefinition(config._l)._meridiemParse;
1184
+ return config._locale._meridiemParse;
1185
+ case 'x':
1186
+ return parseTokenOffsetMs;
989
1187
  case 'X':
990
1188
  return parseTokenTimestampMs;
991
1189
  case 'Z':
@@ -1019,20 +1217,22 @@
1019
1217
  case 'e':
1020
1218
  case 'E':
1021
1219
  return parseTokenOneOrTwoDigits;
1220
+ case 'Do':
1221
+ return strict ? config._locale._ordinalParse : config._locale._ordinalParseLenient;
1022
1222
  default :
1023
- a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), "i"));
1223
+ a = new RegExp(regexpEscape(unescapeFormat(token.replace('\\', '')), 'i'));
1024
1224
  return a;
1025
1225
  }
1026
1226
  }
1027
1227
 
1028
- function timezoneMinutesFromString(string) {
1029
- string = string || "";
1228
+ function utcOffsetFromString(string) {
1229
+ string = string || '';
1030
1230
  var possibleTzMatches = (string.match(parseTokenTimezone) || []),
1031
1231
  tzChunk = possibleTzMatches[possibleTzMatches.length - 1] || [],
1032
1232
  parts = (tzChunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
1033
1233
  minutes = +(parts[1] * 60) + toInt(parts[2]);
1034
1234
 
1035
- return parts[0] === '+' ? -minutes : minutes;
1235
+ return parts[0] === '+' ? minutes : -minutes;
1036
1236
  }
1037
1237
 
1038
1238
  // function to convert string input to date
@@ -1040,6 +1240,12 @@
1040
1240
  var a, datePartArray = config._a;
1041
1241
 
1042
1242
  switch (token) {
1243
+ // QUARTER
1244
+ case 'Q':
1245
+ if (input != null) {
1246
+ datePartArray[MONTH] = (toInt(input) - 1) * 3;
1247
+ }
1248
+ break;
1043
1249
  // MONTH
1044
1250
  case 'M' : // fall through to MM
1045
1251
  case 'MM' :
@@ -1049,7 +1255,7 @@
1049
1255
  break;
1050
1256
  case 'MMM' : // fall through to MMMM
1051
1257
  case 'MMMM' :
1052
- a = getLangDefinition(config._l).monthsParse(input);
1258
+ a = config._locale.monthsParse(input, token, config._strict);
1053
1259
  // if we didn't find a month name, mark the date as invalid.
1054
1260
  if (a != null) {
1055
1261
  datePartArray[MONTH] = a;
@@ -1064,6 +1270,12 @@
1064
1270
  datePartArray[DATE] = toInt(input);
1065
1271
  }
1066
1272
  break;
1273
+ case 'Do' :
1274
+ if (input != null) {
1275
+ datePartArray[DATE] = toInt(parseInt(
1276
+ input.match(/\d{1,2}/)[0], 10));
1277
+ }
1278
+ break;
1067
1279
  // DAY OF YEAR
1068
1280
  case 'DDD' : // fall through to DDDD
1069
1281
  case 'DDDD' :
@@ -1074,7 +1286,7 @@
1074
1286
  break;
1075
1287
  // YEAR
1076
1288
  case 'YY' :
1077
- datePartArray[YEAR] = toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
1289
+ datePartArray[YEAR] = moment.parseTwoDigitYear(input);
1078
1290
  break;
1079
1291
  case 'YYYY' :
1080
1292
  case 'YYYYY' :
@@ -1084,13 +1296,16 @@
1084
1296
  // AM / PM
1085
1297
  case 'a' : // fall through to A
1086
1298
  case 'A' :
1087
- config._isPm = getLangDefinition(config._l).isPM(input);
1299
+ config._meridiem = input;
1300
+ // config._isPm = config._locale.isPM(input);
1088
1301
  break;
1089
- // 24 HOUR
1090
- case 'H' : // fall through to hh
1091
- case 'HH' : // fall through to hh
1302
+ // HOUR
1092
1303
  case 'h' : // fall through to hh
1093
1304
  case 'hh' :
1305
+ config._pf.bigHour = true;
1306
+ /* falls through */
1307
+ case 'H' : // fall through to HH
1308
+ case 'HH' :
1094
1309
  datePartArray[HOUR] = toInt(input);
1095
1310
  break;
1096
1311
  // MINUTE
@@ -1110,6 +1325,10 @@
1110
1325
  case 'SSSS' :
1111
1326
  datePartArray[MILLISECOND] = toInt(('0.' + input) * 1000);
1112
1327
  break;
1328
+ // UNIX OFFSET (MILLISECONDS)
1329
+ case 'x':
1330
+ config._d = new Date(toInt(input));
1331
+ break;
1113
1332
  // UNIX TIMESTAMP WITH MS
1114
1333
  case 'X':
1115
1334
  config._d = new Date(parseFloat(input) * 1000);
@@ -1118,32 +1337,87 @@
1118
1337
  case 'Z' : // fall through to ZZ
1119
1338
  case 'ZZ' :
1120
1339
  config._useUTC = true;
1121
- config._tzm = timezoneMinutesFromString(input);
1340
+ config._tzm = utcOffsetFromString(input);
1341
+ break;
1342
+ // WEEKDAY - human
1343
+ case 'dd':
1344
+ case 'ddd':
1345
+ case 'dddd':
1346
+ a = config._locale.weekdaysParse(input);
1347
+ // if we didn't get a weekday name, mark the date as invalid
1348
+ if (a != null) {
1349
+ config._w = config._w || {};
1350
+ config._w['d'] = a;
1351
+ } else {
1352
+ config._pf.invalidWeekday = input;
1353
+ }
1122
1354
  break;
1355
+ // WEEK, WEEK DAY - numeric
1123
1356
  case 'w':
1124
1357
  case 'ww':
1125
1358
  case 'W':
1126
1359
  case 'WW':
1127
1360
  case 'd':
1128
- case 'dd':
1129
- case 'ddd':
1130
- case 'dddd':
1131
1361
  case 'e':
1132
1362
  case 'E':
1133
1363
  token = token.substr(0, 1);
1134
1364
  /* falls through */
1135
- case 'gg':
1136
1365
  case 'gggg':
1137
- case 'GG':
1138
1366
  case 'GGGG':
1139
1367
  case 'GGGGG':
1140
1368
  token = token.substr(0, 2);
1141
1369
  if (input) {
1142
1370
  config._w = config._w || {};
1143
- config._w[token] = input;
1371
+ config._w[token] = toInt(input);
1144
1372
  }
1145
1373
  break;
1374
+ case 'gg':
1375
+ case 'GG':
1376
+ config._w = config._w || {};
1377
+ config._w[token] = moment.parseTwoDigitYear(input);
1378
+ }
1379
+ }
1380
+
1381
+ function dayOfYearFromWeekInfo(config) {
1382
+ var w, weekYear, week, weekday, dow, doy, temp;
1383
+
1384
+ w = config._w;
1385
+ if (w.GG != null || w.W != null || w.E != null) {
1386
+ dow = 1;
1387
+ doy = 4;
1388
+
1389
+ // TODO: We need to take the current isoWeekYear, but that depends on
1390
+ // how we interpret now (local, utc, fixed offset). So create
1391
+ // a now version of current config (take local/utc/offset flags, and
1392
+ // create now).
1393
+ weekYear = dfl(w.GG, config._a[YEAR], weekOfYear(moment(), 1, 4).year);
1394
+ week = dfl(w.W, 1);
1395
+ weekday = dfl(w.E, 1);
1396
+ } else {
1397
+ dow = config._locale._week.dow;
1398
+ doy = config._locale._week.doy;
1399
+
1400
+ weekYear = dfl(w.gg, config._a[YEAR], weekOfYear(moment(), dow, doy).year);
1401
+ week = dfl(w.w, 1);
1402
+
1403
+ if (w.d != null) {
1404
+ // weekday -- low day numbers are considered next week
1405
+ weekday = w.d;
1406
+ if (weekday < dow) {
1407
+ ++week;
1408
+ }
1409
+ } else if (w.e != null) {
1410
+ // local weekday -- counting starts from begining of week
1411
+ weekday = w.e + dow;
1412
+ } else {
1413
+ // default to begining of week
1414
+ weekday = dow;
1415
+ }
1146
1416
  }
1417
+ temp = dayOfYearFromWeeks(weekYear, week, weekday, doy, dow);
1418
+
1419
+ config._a[YEAR] = temp.year;
1420
+ config._dayOfYear = temp.dayOfYear;
1147
1421
  }
1148
1422
 
1149
1423
  // convert an array to a date.
@@ -1151,8 +1425,7 @@
1151
1425
  // note: all values past the year are optional and will default to the lowest possible value.
1152
1426
  // [year, month, day , hour, minute, second, millisecond]
1153
1427
  function dateFromConfig(config) {
1154
- var i, date, input = [], currentDate,
1155
- yearToUse, fixYear, w, temp, lang, weekday, week;
1428
+ var i, date, input = [], currentDate, yearToUse;
1156
1429
 
1157
1430
  if (config._d) {
1158
1431
  return;
@@ -1162,39 +1435,12 @@
1162
1435
 
1163
1436
  //compute day of the year from weeks and weekdays
1164
1437
  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;
1438
+ dayOfYearFromWeekInfo(config);
1193
1439
  }
1194
1440
 
1195
1441
  //if the day of the year is set, figure out what it is
1196
1442
  if (config._dayOfYear) {
1197
- yearToUse = config._a[YEAR] == null ? currentDate[YEAR] : config._a[YEAR];
1443
+ yearToUse = dfl(config._a[YEAR], currentDate[YEAR]);
1198
1444
 
1199
1445
  if (config._dayOfYear > daysInYear(yearToUse)) {
1200
1446
  config._pf._overflowDayOfYear = true;
@@ -1219,11 +1465,25 @@
1219
1465
  config._a[i] = input[i] = (config._a[i] == null) ? (i === 2 ? 1 : 0) : config._a[i];
1220
1466
  }
1221
1467
 
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);
1468
+ // Check for 24:00:00.000
1469
+ if (config._a[HOUR] === 24 &&
1470
+ config._a[MINUTE] === 0 &&
1471
+ config._a[SECOND] === 0 &&
1472
+ config._a[MILLISECOND] === 0) {
1473
+ config._nextDay = true;
1474
+ config._a[HOUR] = 0;
1475
+ }
1225
1476
 
1226
1477
  config._d = (config._useUTC ? makeUTCDate : makeDate).apply(null, input);
1478
+ // Apply timezone offset from input. The actual utcOffset can be changed
1479
+ // with parseZone.
1480
+ if (config._tzm != null) {
1481
+ config._d.setUTCMinutes(config._d.getUTCMinutes() - config._tzm);
1482
+ }
1483
+
1484
+ if (config._nextDay) {
1485
+ config._a[HOUR] = 24;
1486
+ }
1227
1487
  }
1228
1488
 
1229
1489
  function dateFromObject(config) {
@@ -1237,7 +1497,7 @@
1237
1497
  config._a = [
1238
1498
  normalizedInput.year,
1239
1499
  normalizedInput.month,
1240
- normalizedInput.day,
1500
+ normalizedInput.day || normalizedInput.date,
1241
1501
  normalizedInput.hour,
1242
1502
  normalizedInput.minute,
1243
1503
  normalizedInput.second,
@@ -1262,18 +1522,21 @@
1262
1522
 
1263
1523
  // date from string and format string
1264
1524
  function makeDateFromStringAndFormat(config) {
1525
+ if (config._f === moment.ISO_8601) {
1526
+ parseISO(config);
1527
+ return;
1528
+ }
1265
1529
 
1266
1530
  config._a = [];
1267
1531
  config._pf.empty = true;
1268
1532
 
1269
1533
  // 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,
1534
+ var string = '' + config._i,
1272
1535
  i, parsedInput, tokens, token, skipped,
1273
1536
  stringLength = string.length,
1274
1537
  totalParsedInputLength = 0;
1275
1538
 
1276
- tokens = expandFormat(config._f, lang).match(formattingTokens) || [];
1539
+ tokens = expandFormat(config._f, config._locale).match(formattingTokens) || [];
1277
1540
 
1278
1541
  for (i = 0; i < tokens.length; i++) {
1279
1542
  token = tokens[i];
@@ -1307,15 +1570,13 @@
1307
1570
  config._pf.unusedInput.push(string);
1308
1571
  }
1309
1572
 
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;
1573
+ // clear _12h flag if hour is <= 12
1574
+ if (config._pf.bigHour === true && config._a[HOUR] <= 12) {
1575
+ config._pf.bigHour = undefined;
1317
1576
  }
1318
-
1577
+ // handle meridiem
1578
+ config._a[HOUR] = meridiemFixWrap(config._locale, config._a[HOUR],
1579
+ config._meridiem);
1319
1580
  dateFromConfig(config);
1320
1581
  checkOverflow(config);
1321
1582
  }
@@ -1348,7 +1609,10 @@
1348
1609
 
1349
1610
  for (i = 0; i < config._f.length; i++) {
1350
1611
  currentScore = 0;
1351
- tempConfig = extend({}, config);
1612
+ tempConfig = copyConfig({}, config);
1613
+ if (config._useUTC != null) {
1614
+ tempConfig._useUTC = config._useUTC;
1615
+ }
1352
1616
  tempConfig._pf = defaultParsingFlags();
1353
1617
  tempConfig._f = config._f[i];
1354
1618
  makeDateFromStringAndFormat(tempConfig);
@@ -1375,7 +1639,7 @@
1375
1639
  }
1376
1640
 
1377
1641
  // date from iso format
1378
- function makeDateFromString(config) {
1642
+ function parseISO(config) {
1379
1643
  var i, l,
1380
1644
  string = config._i,
1381
1645
  match = isoRegex.exec(string);
@@ -1384,8 +1648,8 @@
1384
1648
  config._pf.iso = true;
1385
1649
  for (i = 0, l = isoDates.length; i < l; i++) {
1386
1650
  if (isoDates[i][1].exec(string)) {
1387
- // match[5] should be "T" or undefined
1388
- config._f = isoDates[i][0] + (match[6] || " ");
1651
+ // match[5] should be 'T' or undefined
1652
+ config._f = isoDates[i][0] + (match[6] || ' ');
1389
1653
  break;
1390
1654
  }
1391
1655
  }
@@ -1396,34 +1660,53 @@
1396
1660
  }
1397
1661
  }
1398
1662
  if (string.match(parseTokenTimezone)) {
1399
- config._f += "Z";
1663
+ config._f += 'Z';
1400
1664
  }
1401
1665
  makeDateFromStringAndFormat(config);
1666
+ } else {
1667
+ config._isValid = false;
1402
1668
  }
1403
- else {
1404
- config._d = new Date(string);
1669
+ }
1670
+
1671
+ // date from iso format or fallback
1672
+ function makeDateFromString(config) {
1673
+ parseISO(config);
1674
+ if (config._isValid === false) {
1675
+ delete config._isValid;
1676
+ moment.createFromInputFallback(config);
1405
1677
  }
1406
1678
  }
1407
1679
 
1408
- function makeDateFromInput(config) {
1409
- var input = config._i,
1410
- matched = aspNetJsonRegex.exec(input);
1680
+ function map(arr, fn) {
1681
+ var res = [], i;
1682
+ for (i = 0; i < arr.length; ++i) {
1683
+ res.push(fn(arr[i], i));
1684
+ }
1685
+ return res;
1686
+ }
1411
1687
 
1688
+ function makeDateFromInput(config) {
1689
+ var input = config._i, matched;
1412
1690
  if (input === undefined) {
1413
1691
  config._d = new Date();
1414
- } else if (matched) {
1692
+ } else if (isDate(input)) {
1693
+ config._d = new Date(+input);
1694
+ } else if ((matched = aspNetJsonRegex.exec(input)) !== null) {
1415
1695
  config._d = new Date(+matched[1]);
1416
1696
  } else if (typeof input === 'string') {
1417
1697
  makeDateFromString(config);
1418
1698
  } else if (isArray(input)) {
1419
- config._a = input.slice(0);
1699
+ config._a = map(input.slice(0), function (obj) {
1700
+ return parseInt(obj, 10);
1701
+ });
1420
1702
  dateFromConfig(config);
1421
- } else if (isDate(input)) {
1422
- config._d = new Date(+input);
1423
1703
  } else if (typeof(input) === 'object') {
1424
1704
  dateFromObject(config);
1425
- } else {
1705
+ } else if (typeof(input) === 'number') {
1706
+ // from milliseconds
1426
1707
  config._d = new Date(input);
1708
+ } else {
1709
+ moment.createFromInputFallback(config);
1427
1710
  }
1428
1711
  }
1429
1712
 
@@ -1447,13 +1730,13 @@
1447
1730
  return date;
1448
1731
  }
1449
1732
 
1450
- function parseWeekday(input, language) {
1733
+ function parseWeekday(input, locale) {
1451
1734
  if (typeof input === 'string') {
1452
1735
  if (!isNaN(input)) {
1453
1736
  input = parseInt(input, 10);
1454
1737
  }
1455
1738
  else {
1456
- input = language.weekdaysParse(input);
1739
+ input = locale.weekdaysParse(input);
1457
1740
  if (typeof input !== 'number') {
1458
1741
  return null;
1459
1742
  }
@@ -1468,29 +1751,33 @@
1468
1751
 
1469
1752
 
1470
1753
  // 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);
1754
+ function substituteTimeAgo(string, number, withoutSuffix, isFuture, locale) {
1755
+ return locale.relativeTime(number || 1, !!withoutSuffix, string, isFuture);
1473
1756
  }
1474
1757
 
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] ||
1758
+ function relativeTime(posNegDuration, withoutSuffix, locale) {
1759
+ var duration = moment.duration(posNegDuration).abs(),
1760
+ seconds = round(duration.as('s')),
1761
+ minutes = round(duration.as('m')),
1762
+ hours = round(duration.as('h')),
1763
+ days = round(duration.as('d')),
1764
+ months = round(duration.as('M')),
1765
+ years = round(duration.as('y')),
1766
+
1767
+ args = seconds < relativeTimeThresholds.s && ['s', seconds] ||
1482
1768
  minutes === 1 && ['m'] ||
1483
- minutes < 45 && ['mm', minutes] ||
1769
+ minutes < relativeTimeThresholds.m && ['mm', minutes] ||
1484
1770
  hours === 1 && ['h'] ||
1485
- hours < 22 && ['hh', hours] ||
1771
+ hours < relativeTimeThresholds.h && ['hh', hours] ||
1486
1772
  days === 1 && ['d'] ||
1487
- days <= 25 && ['dd', days] ||
1488
- days <= 45 && ['M'] ||
1489
- days < 345 && ['MM', round(days / 30)] ||
1773
+ days < relativeTimeThresholds.d && ['dd', days] ||
1774
+ months === 1 && ['M'] ||
1775
+ months < relativeTimeThresholds.M && ['MM', months] ||
1490
1776
  years === 1 && ['y'] || ['yy', years];
1777
+
1491
1778
  args[2] = withoutSuffix;
1492
- args[3] = milliseconds > 0;
1493
- args[4] = lang;
1779
+ args[3] = +posNegDuration > 0;
1780
+ args[4] = locale;
1494
1781
  return substituteTimeAgo.apply({}, args);
1495
1782
  }
1496
1783
 
@@ -1521,7 +1808,7 @@
1521
1808
  daysToDayOfWeek += 7;
1522
1809
  }
1523
1810
 
1524
- adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
1811
+ adjustedMoment = moment(mom).add(daysToDayOfWeek, 'd');
1525
1812
  return {
1526
1813
  week: Math.ceil(adjustedMoment.dayOfYear() / 7),
1527
1814
  year: adjustedMoment.year()
@@ -1532,6 +1819,7 @@
1532
1819
  function dayOfYearFromWeeks(year, week, weekday, firstDayOfWeekOfYear, firstDayOfWeek) {
1533
1820
  var d = makeUTCDate(year, 0, 1).getUTCDay(), daysToAdd, dayOfYear;
1534
1821
 
1822
+ d = d === 0 ? 7 : d;
1535
1823
  weekday = weekday != null ? weekday : firstDayOfWeek;
1536
1824
  daysToAdd = firstDayOfWeek - d + (d > firstDayOfWeekOfYear ? 7 : 0) - (d < firstDayOfWeek ? 7 : 0);
1537
1825
  dayOfYear = 7 * (week - 1) + (weekday - firstDayOfWeek) + daysToAdd + 1;
@@ -1548,20 +1836,21 @@
1548
1836
 
1549
1837
  function makeMoment(config) {
1550
1838
  var input = config._i,
1551
- format = config._f;
1839
+ format = config._f,
1840
+ res;
1841
+
1842
+ config._locale = config._locale || moment.localeData(config._l);
1552
1843
 
1553
- if (input === null) {
1844
+ if (input === null || (format === undefined && input === '')) {
1554
1845
  return moment.invalid({nullInput: true});
1555
1846
  }
1556
1847
 
1557
1848
  if (typeof input === 'string') {
1558
- config._i = input = getLangDefinition().preparse(input);
1849
+ config._i = input = config._locale.preparse(input);
1559
1850
  }
1560
1851
 
1561
1852
  if (moment.isMoment(input)) {
1562
- config = cloneMoment(input);
1563
-
1564
- config._d = new Date(+input._d);
1853
+ return new Moment(input, true);
1565
1854
  } else if (format) {
1566
1855
  if (isArray(format)) {
1567
1856
  makeDateFromStringAndArray(config);
@@ -1572,15 +1861,22 @@
1572
1861
  makeDateFromInput(config);
1573
1862
  }
1574
1863
 
1575
- return new Moment(config);
1864
+ res = new Moment(config);
1865
+ if (res._nextDay) {
1866
+ // Adding is smart enough around DST
1867
+ res.add(1, 'd');
1868
+ res._nextDay = undefined;
1869
+ }
1870
+
1871
+ return res;
1576
1872
  }
1577
1873
 
1578
- moment = function (input, format, lang, strict) {
1874
+ moment = function (input, format, locale, strict) {
1579
1875
  var c;
1580
1876
 
1581
- if (typeof(lang) === "boolean") {
1582
- strict = lang;
1583
- lang = undefined;
1877
+ if (typeof(locale) === 'boolean') {
1878
+ strict = locale;
1879
+ locale = undefined;
1584
1880
  }
1585
1881
  // object construction must be done this way.
1586
1882
  // https://github.com/moment/moment/issues/1423
@@ -1588,7 +1884,7 @@
1588
1884
  c._isAMomentObject = true;
1589
1885
  c._i = input;
1590
1886
  c._f = format;
1591
- c._l = lang;
1887
+ c._l = locale;
1592
1888
  c._strict = strict;
1593
1889
  c._isUTC = false;
1594
1890
  c._pf = defaultParsingFlags();
@@ -1596,13 +1892,59 @@
1596
1892
  return makeMoment(c);
1597
1893
  };
1598
1894
 
1895
+ moment.suppressDeprecationWarnings = false;
1896
+
1897
+ moment.createFromInputFallback = deprecate(
1898
+ 'moment construction falls back to js Date. This is ' +
1899
+ 'discouraged and will be removed in upcoming major ' +
1900
+ 'release. Please refer to ' +
1901
+ 'https://github.com/moment/moment/issues/1407 for more info.',
1902
+ function (config) {
1903
+ config._d = new Date(config._i + (config._useUTC ? ' UTC' : ''));
1904
+ }
1905
+ );
1906
+
1907
+ // Pick a moment m from moments so that m[fn](other) is true for all
1908
+ // other. This relies on the function fn to be transitive.
1909
+ //
1910
+ // moments should either be an array of moment objects or an array, whose
1911
+ // first element is an array of moment objects.
1912
+ function pickBy(fn, moments) {
1913
+ var res, i;
1914
+ if (moments.length === 1 && isArray(moments[0])) {
1915
+ moments = moments[0];
1916
+ }
1917
+ if (!moments.length) {
1918
+ return moment();
1919
+ }
1920
+ res = moments[0];
1921
+ for (i = 1; i < moments.length; ++i) {
1922
+ if (moments[i][fn](res)) {
1923
+ res = moments[i];
1924
+ }
1925
+ }
1926
+ return res;
1927
+ }
1928
+
1929
+ moment.min = function () {
1930
+ var args = [].slice.call(arguments, 0);
1931
+
1932
+ return pickBy('isBefore', args);
1933
+ };
1934
+
1935
+ moment.max = function () {
1936
+ var args = [].slice.call(arguments, 0);
1937
+
1938
+ return pickBy('isAfter', args);
1939
+ };
1940
+
1599
1941
  // creating with utc
1600
- moment.utc = function (input, format, lang, strict) {
1942
+ moment.utc = function (input, format, locale, strict) {
1601
1943
  var c;
1602
1944
 
1603
- if (typeof(lang) === "boolean") {
1604
- strict = lang;
1605
- lang = undefined;
1945
+ if (typeof(locale) === 'boolean') {
1946
+ strict = locale;
1947
+ locale = undefined;
1606
1948
  }
1607
1949
  // object construction must be done this way.
1608
1950
  // https://github.com/moment/moment/issues/1423
@@ -1610,7 +1952,7 @@
1610
1952
  c._isAMomentObject = true;
1611
1953
  c._useUTC = true;
1612
1954
  c._isUTC = true;
1613
- c._l = lang;
1955
+ c._l = locale;
1614
1956
  c._i = input;
1615
1957
  c._f = format;
1616
1958
  c._strict = strict;
@@ -1631,7 +1973,8 @@
1631
1973
  match = null,
1632
1974
  sign,
1633
1975
  ret,
1634
- parseIso;
1976
+ parseIso,
1977
+ diffRes;
1635
1978
 
1636
1979
  if (moment.isDuration(input)) {
1637
1980
  duration = {
@@ -1647,7 +1990,7 @@
1647
1990
  duration.milliseconds = input;
1648
1991
  }
1649
1992
  } else if (!!(match = aspNetTimeSpanJsonRegex.exec(input))) {
1650
- sign = (match[1] === "-") ? -1 : 1;
1993
+ sign = (match[1] === '-') ? -1 : 1;
1651
1994
  duration = {
1652
1995
  y: 0,
1653
1996
  d: toInt(match[DATE]) * sign,
@@ -1657,7 +2000,7 @@
1657
2000
  ms: toInt(match[MILLISECOND]) * sign
1658
2001
  };
1659
2002
  } else if (!!(match = isoDurationRegex.exec(input))) {
1660
- sign = (match[1] === "-") ? -1 : 1;
2003
+ sign = (match[1] === '-') ? -1 : 1;
1661
2004
  parseIso = function (inp) {
1662
2005
  // We'd normally use ~~inp for this, but unfortunately it also
1663
2006
  // converts floats to ints.
@@ -1675,12 +2018,21 @@
1675
2018
  s: parseIso(match[7]),
1676
2019
  w: parseIso(match[8])
1677
2020
  };
2021
+ } else if (duration == null) {// checks for null or undefined
2022
+ duration = {};
2023
+ } else if (typeof duration === 'object' &&
2024
+ ('from' in duration || 'to' in duration)) {
2025
+ diffRes = momentsDifference(moment(duration.from), moment(duration.to));
2026
+
2027
+ duration = {};
2028
+ duration.ms = diffRes.milliseconds;
2029
+ duration.M = diffRes.months;
1678
2030
  }
1679
2031
 
1680
2032
  ret = new Duration(duration);
1681
2033
 
1682
- if (moment.isDuration(input) && input.hasOwnProperty('_lang')) {
1683
- ret._lang = input._lang;
2034
+ if (moment.isDuration(input) && hasOwnProp(input, '_locale')) {
2035
+ ret._locale = input._locale;
1684
2036
  }
1685
2037
 
1686
2038
  return ret;
@@ -1692,42 +2044,111 @@
1692
2044
  // default format
1693
2045
  moment.defaultFormat = isoFormat;
1694
2046
 
2047
+ // constant that refers to the ISO standard
2048
+ moment.ISO_8601 = function () {};
2049
+
2050
+ // Plugins that add properties should also add the key here (null value),
2051
+ // so we can properly clone ourselves.
2052
+ moment.momentProperties = momentProperties;
2053
+
1695
2054
  // This function will be called whenever a moment is mutated.
1696
2055
  // It is intended to keep the offset in sync with the timezone.
1697
2056
  moment.updateOffset = function () {};
1698
2057
 
1699
- // This function will load languages and then set the global language. If
2058
+ // This function allows you to set a threshold for relative time strings
2059
+ moment.relativeTimeThreshold = function (threshold, limit) {
2060
+ if (relativeTimeThresholds[threshold] === undefined) {
2061
+ return false;
2062
+ }
2063
+ if (limit === undefined) {
2064
+ return relativeTimeThresholds[threshold];
2065
+ }
2066
+ relativeTimeThresholds[threshold] = limit;
2067
+ return true;
2068
+ };
2069
+
2070
+ moment.lang = deprecate(
2071
+ 'moment.lang is deprecated. Use moment.locale instead.',
2072
+ function (key, value) {
2073
+ return moment.locale(key, value);
2074
+ }
2075
+ );
2076
+
2077
+ // This function will load locale and then set the global locale. If
1700
2078
  // 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;
2079
+ // locale key.
2080
+ moment.locale = function (key, values) {
2081
+ var data;
2082
+ if (key) {
2083
+ if (typeof(values) !== 'undefined') {
2084
+ data = moment.defineLocale(key, values);
2085
+ }
2086
+ else {
2087
+ data = moment.localeData(key);
2088
+ }
2089
+
2090
+ if (data) {
2091
+ moment.duration._locale = moment._locale = data;
2092
+ }
2093
+ }
2094
+
2095
+ return moment._locale._abbr;
2096
+ };
2097
+
2098
+ moment.defineLocale = function (name, values) {
2099
+ if (values !== null) {
2100
+ values.abbr = name;
2101
+ if (!locales[name]) {
2102
+ locales[name] = new Locale();
2103
+ }
2104
+ locales[name].set(values);
2105
+
2106
+ // backwards compat for now: also set the locale
2107
+ moment.locale(name);
2108
+
2109
+ return locales[name];
2110
+ } else {
2111
+ // useful for testing
2112
+ delete locales[name];
2113
+ return null;
2114
+ }
1717
2115
  };
1718
2116
 
1719
- // returns language data
1720
- moment.langData = function (key) {
1721
- if (key && key._lang && key._lang._abbr) {
1722
- key = key._lang._abbr;
2117
+ moment.langData = deprecate(
2118
+ 'moment.langData is deprecated. Use moment.localeData instead.',
2119
+ function (key) {
2120
+ return moment.localeData(key);
1723
2121
  }
1724
- return getLangDefinition(key);
2122
+ );
2123
+
2124
+ // returns locale data
2125
+ moment.localeData = function (key) {
2126
+ var locale;
2127
+
2128
+ if (key && key._locale && key._locale._abbr) {
2129
+ key = key._locale._abbr;
2130
+ }
2131
+
2132
+ if (!key) {
2133
+ return moment._locale;
2134
+ }
2135
+
2136
+ if (!isArray(key)) {
2137
+ //short-circuit everything else
2138
+ locale = loadLocale(key);
2139
+ if (locale) {
2140
+ return locale;
2141
+ }
2142
+ key = [key];
2143
+ }
2144
+
2145
+ return chooseLocale(key);
1725
2146
  };
1726
2147
 
1727
2148
  // compare moment object
1728
2149
  moment.isMoment = function (obj) {
1729
2150
  return obj instanceof Moment ||
1730
- (obj != null && obj.hasOwnProperty('_isAMomentObject'));
2151
+ (obj != null && hasOwnProp(obj, '_isAMomentObject'));
1731
2152
  };
1732
2153
 
1733
2154
  // for typechecking Duration objects
@@ -1755,10 +2176,16 @@
1755
2176
  return m;
1756
2177
  };
1757
2178
 
1758
- moment.parseZone = function (input) {
1759
- return moment(input).parseZone();
2179
+ moment.parseZone = function () {
2180
+ return moment.apply(null, arguments).parseZone();
1760
2181
  };
1761
2182
 
2183
+ moment.parseTwoDigitYear = function (input) {
2184
+ return toInt(input) + (toInt(input) > 68 ? 1900 : 2000);
2185
+ };
2186
+
2187
+ moment.isDate = isDate;
2188
+
1762
2189
  /************************************
1763
2190
  Moment Prototype
1764
2191
  ************************************/
@@ -1771,7 +2198,7 @@
1771
2198
  },
1772
2199
 
1773
2200
  valueOf : function () {
1774
- return +this._d + ((this._offset || 0) * 60000);
2201
+ return +this._d - ((this._offset || 0) * 60000);
1775
2202
  },
1776
2203
 
1777
2204
  unix : function () {
@@ -1779,7 +2206,7 @@
1779
2206
  },
1780
2207
 
1781
2208
  toString : function () {
1782
- return this.clone().lang('en').format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ");
2209
+ return this.clone().locale('en').format('ddd MMM DD YYYY HH:mm:ss [GMT]ZZ');
1783
2210
  },
1784
2211
 
1785
2212
  toDate : function () {
@@ -1789,7 +2216,12 @@
1789
2216
  toISOString : function () {
1790
2217
  var m = moment(this).utc();
1791
2218
  if (0 < m.year() && m.year() <= 9999) {
1792
- return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
2219
+ if ('function' === typeof Date.prototype.toISOString) {
2220
+ // native implementation is ~50x faster, use it when we can
2221
+ return this.toDate().toISOString();
2222
+ } else {
2223
+ return formatMoment(m, 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
2224
+ }
1793
2225
  } else {
1794
2226
  return formatMoment(m, 'YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1795
2227
  }
@@ -1813,7 +2245,6 @@
1813
2245
  },
1814
2246
 
1815
2247
  isDSTShifted : function () {
1816
-
1817
2248
  if (this._a) {
1818
2249
  return this.isValid() && compareArrays(this._a, (this._isUTC ? moment.utc(this._a) : moment(this._a)).toArray()) > 0;
1819
2250
  }
@@ -1829,69 +2260,47 @@
1829
2260
  return this._pf.overflow;
1830
2261
  },
1831
2262
 
1832
- utc : function () {
1833
- return this.zone(0);
2263
+ utc : function (keepLocalTime) {
2264
+ return this.utcOffset(0, keepLocalTime);
1834
2265
  },
1835
2266
 
1836
- local : function () {
1837
- this.zone(0);
1838
- this._isUTC = false;
2267
+ local : function (keepLocalTime) {
2268
+ if (this._isUTC) {
2269
+ this.utcOffset(0, keepLocalTime);
2270
+ this._isUTC = false;
2271
+
2272
+ if (keepLocalTime) {
2273
+ this.subtract(this._dateUtcOffset(), 'm');
2274
+ }
2275
+ }
1839
2276
  return this;
1840
2277
  },
1841
2278
 
1842
2279
  format : function (inputString) {
1843
2280
  var output = formatMoment(this, inputString || moment.defaultFormat);
1844
- return this.lang().postformat(output);
2281
+ return this.localeData().postformat(output);
1845
2282
  },
1846
2283
 
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
- },
2284
+ add : createAdder(1, 'add'),
1858
2285
 
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
- },
2286
+ subtract : createAdder(-1, 'subtract'),
1870
2287
 
1871
2288
  diff : function (input, units, asFloat) {
1872
2289
  var that = makeAs(input, this),
1873
- zoneDiff = (this.zone() - that.zone()) * 6e4,
1874
- diff, output;
2290
+ zoneDiff = (that.utcOffset() - this.utcOffset()) * 6e4,
2291
+ anchor, diff, output, daysAdjust;
1875
2292
 
1876
2293
  units = normalizeUnits(units);
1877
2294
 
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') {
2295
+ if (units === 'year' || units === 'month' || units === 'quarter') {
2296
+ output = monthDiff(this, that);
2297
+ if (units === 'quarter') {
2298
+ output = output / 3;
2299
+ } else if (units === 'year') {
1891
2300
  output = output / 12;
1892
2301
  }
1893
2302
  } else {
1894
- diff = (this - that);
2303
+ diff = this - that;
1895
2304
  output = units === 'second' ? diff / 1e3 : // 1000
1896
2305
  units === 'minute' ? diff / 6e4 : // 1000 * 60
1897
2306
  units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
@@ -1903,17 +2312,19 @@
1903
2312
  },
1904
2313
 
1905
2314
  from : function (time, withoutSuffix) {
1906
- return moment.duration(this.diff(time)).lang(this.lang()._abbr).humanize(!withoutSuffix);
2315
+ return moment.duration({to: this, from: time}).locale(this.locale()).humanize(!withoutSuffix);
1907
2316
  },
1908
2317
 
1909
2318
  fromNow : function (withoutSuffix) {
1910
2319
  return this.from(moment(), withoutSuffix);
1911
2320
  },
1912
2321
 
1913
- calendar : function () {
2322
+ calendar : function (time) {
1914
2323
  // 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'),
2324
+ // Getting start-of-today depends on whether we're locat/utc/offset
2325
+ // or not.
2326
+ var now = time || moment(),
2327
+ sod = makeAs(now, this).startOf('day'),
1917
2328
  diff = this.diff(sod, 'days', true),
1918
2329
  format = diff < -6 ? 'sameElse' :
1919
2330
  diff < -1 ? 'lastWeek' :
@@ -1921,7 +2332,7 @@
1921
2332
  diff < 1 ? 'sameDay' :
1922
2333
  diff < 2 ? 'nextDay' :
1923
2334
  diff < 7 ? 'nextWeek' : 'sameElse';
1924
- return this.format(this.lang().calendar(format, this));
2335
+ return this.format(this.localeData().calendar(format, this, moment(now)));
1925
2336
  },
1926
2337
 
1927
2338
  isLeapYear : function () {
@@ -1929,45 +2340,23 @@
1929
2340
  },
1930
2341
 
1931
2342
  isDST : function () {
1932
- return (this.zone() < this.clone().month(0).zone() ||
1933
- this.zone() < this.clone().month(5).zone());
2343
+ return (this.utcOffset() > this.clone().month(0).utcOffset() ||
2344
+ this.utcOffset() > this.clone().month(5).utcOffset());
1934
2345
  },
1935
2346
 
1936
2347
  day : function (input) {
1937
2348
  var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1938
2349
  if (input != null) {
1939
- input = parseWeekday(input, this.lang());
1940
- return this.add({ d : input - day });
2350
+ input = parseWeekday(input, this.localeData());
2351
+ return this.add(input - day, 'd');
1941
2352
  } else {
1942
2353
  return day;
1943
2354
  }
1944
2355
  },
1945
2356
 
1946
- month : function (input) {
1947
- var utc = this._isUTC ? 'UTC' : '',
1948
- dayOfMonth;
2357
+ month : makeAccessor('Month', true),
1949
2358
 
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) {
2359
+ startOf : function (units) {
1971
2360
  units = normalizeUnits(units);
1972
2361
  // the following switch intentionally omits break keywords
1973
2362
  // to utilize falling through the cases.
@@ -1975,6 +2364,7 @@
1975
2364
  case 'year':
1976
2365
  this.month(0);
1977
2366
  /* falls through */
2367
+ case 'quarter':
1978
2368
  case 'month':
1979
2369
  this.date(1);
1980
2370
  /* falls through */
@@ -2001,72 +2391,166 @@
2001
2391
  this.isoWeekday(1);
2002
2392
  }
2003
2393
 
2394
+ // quarters are also special
2395
+ if (units === 'quarter') {
2396
+ this.month(Math.floor(this.month() / 3) * 3);
2397
+ }
2398
+
2004
2399
  return this;
2005
2400
  },
2006
2401
 
2007
2402
  endOf: function (units) {
2008
2403
  units = normalizeUnits(units);
2009
- return this.startOf(units).add((units === 'isoWeek' ? 'week' : units), 1).subtract('ms', 1);
2404
+ if (units === undefined || units === 'millisecond') {
2405
+ return this;
2406
+ }
2407
+ return this.startOf(units).add(1, (units === 'isoWeek' ? 'week' : units)).subtract(1, 'ms');
2010
2408
  },
2011
2409
 
2012
2410
  isAfter: function (input, units) {
2013
- units = typeof units !== 'undefined' ? units : 'millisecond';
2014
- return +this.clone().startOf(units) > +moment(input).startOf(units);
2411
+ var inputMs;
2412
+ units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
2413
+ if (units === 'millisecond') {
2414
+ input = moment.isMoment(input) ? input : moment(input);
2415
+ return +this > +input;
2416
+ } else {
2417
+ inputMs = moment.isMoment(input) ? +input : +moment(input);
2418
+ return inputMs < +this.clone().startOf(units);
2419
+ }
2015
2420
  },
2016
2421
 
2017
2422
  isBefore: function (input, units) {
2018
- units = typeof units !== 'undefined' ? units : 'millisecond';
2019
- return +this.clone().startOf(units) < +moment(input).startOf(units);
2423
+ var inputMs;
2424
+ units = normalizeUnits(typeof units !== 'undefined' ? units : 'millisecond');
2425
+ if (units === 'millisecond') {
2426
+ input = moment.isMoment(input) ? input : moment(input);
2427
+ return +this < +input;
2428
+ } else {
2429
+ inputMs = moment.isMoment(input) ? +input : +moment(input);
2430
+ return +this.clone().endOf(units) < inputMs;
2431
+ }
2020
2432
  },
2021
2433
 
2022
- isSame: function (input, units) {
2023
- units = units || 'ms';
2024
- return +this.clone().startOf(units) === +makeAs(input, this).startOf(units);
2434
+ isBetween: function (from, to, units) {
2435
+ return this.isAfter(from, units) && this.isBefore(to, units);
2025
2436
  },
2026
2437
 
2027
- min: function (other) {
2028
- other = moment.apply(null, arguments);
2029
- return other < this ? this : other;
2438
+ isSame: function (input, units) {
2439
+ var inputMs;
2440
+ units = normalizeUnits(units || 'millisecond');
2441
+ if (units === 'millisecond') {
2442
+ input = moment.isMoment(input) ? input : moment(input);
2443
+ return +this === +input;
2444
+ } else {
2445
+ inputMs = +moment(input);
2446
+ return +(this.clone().startOf(units)) <= inputMs && inputMs <= +(this.clone().endOf(units));
2447
+ }
2030
2448
  },
2031
2449
 
2032
- max: function (other) {
2033
- other = moment.apply(null, arguments);
2034
- return other > this ? this : other;
2035
- },
2450
+ min: deprecate(
2451
+ 'moment().min is deprecated, use moment.min instead. https://github.com/moment/moment/issues/1548',
2452
+ function (other) {
2453
+ other = moment.apply(null, arguments);
2454
+ return other < this ? this : other;
2455
+ }
2456
+ ),
2036
2457
 
2037
- zone : function (input) {
2038
- var offset = this._offset || 0;
2458
+ max: deprecate(
2459
+ 'moment().max is deprecated, use moment.max instead. https://github.com/moment/moment/issues/1548',
2460
+ function (other) {
2461
+ other = moment.apply(null, arguments);
2462
+ return other > this ? this : other;
2463
+ }
2464
+ ),
2465
+
2466
+ zone : deprecate(
2467
+ 'moment().zone is deprecated, use moment().utcOffset instead. ' +
2468
+ 'https://github.com/moment/moment/issues/1779',
2469
+ function (input, keepLocalTime) {
2470
+ if (input != null) {
2471
+ if (typeof input !== 'string') {
2472
+ input = -input;
2473
+ }
2474
+
2475
+ this.utcOffset(input, keepLocalTime);
2476
+
2477
+ return this;
2478
+ } else {
2479
+ return -this.utcOffset();
2480
+ }
2481
+ }
2482
+ ),
2483
+
2484
+ // keepLocalTime = true means only change the timezone, without
2485
+ // affecting the local hour. So 5:31:26 +0300 --[utcOffset(2, true)]-->
2486
+ // 5:31:26 +0200 It is possible that 5:31:26 doesn't exist with offset
2487
+ // +0200, so we adjust the time as needed, to be valid.
2488
+ //
2489
+ // Keeping the time actually adds/subtracts (one hour)
2490
+ // from the actual represented time. That is why we call updateOffset
2491
+ // a second time. In case it wants us to change the offset again
2492
+ // _changeInProgress == true case, then we have to adjust, because
2493
+ // there is no such time in the given timezone.
2494
+ utcOffset : function (input, keepLocalTime) {
2495
+ var offset = this._offset || 0,
2496
+ localAdjust;
2039
2497
  if (input != null) {
2040
- if (typeof input === "string") {
2041
- input = timezoneMinutesFromString(input);
2498
+ if (typeof input === 'string') {
2499
+ input = utcOffsetFromString(input);
2042
2500
  }
2043
2501
  if (Math.abs(input) < 16) {
2044
2502
  input = input * 60;
2045
2503
  }
2504
+ if (!this._isUTC && keepLocalTime) {
2505
+ localAdjust = this._dateUtcOffset();
2506
+ }
2046
2507
  this._offset = input;
2047
2508
  this._isUTC = true;
2509
+ if (localAdjust != null) {
2510
+ this.add(localAdjust, 'm');
2511
+ }
2048
2512
  if (offset !== input) {
2049
- addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
2513
+ if (!keepLocalTime || this._changeInProgress) {
2514
+ addOrSubtractDurationFromMoment(this,
2515
+ moment.duration(input - offset, 'm'), 1, false);
2516
+ } else if (!this._changeInProgress) {
2517
+ this._changeInProgress = true;
2518
+ moment.updateOffset(this, true);
2519
+ this._changeInProgress = null;
2520
+ }
2050
2521
  }
2522
+
2523
+ return this;
2051
2524
  } else {
2052
- return this._isUTC ? offset : this._d.getTimezoneOffset();
2525
+ return this._isUTC ? offset : this._dateUtcOffset();
2053
2526
  }
2054
- return this;
2527
+ },
2528
+
2529
+ isLocal : function () {
2530
+ return !this._isUTC;
2531
+ },
2532
+
2533
+ isUtcOffset : function () {
2534
+ return this._isUTC;
2535
+ },
2536
+
2537
+ isUtc : function () {
2538
+ return this._isUTC && this._offset === 0;
2055
2539
  },
2056
2540
 
2057
2541
  zoneAbbr : function () {
2058
- return this._isUTC ? "UTC" : "";
2542
+ return this._isUTC ? 'UTC' : '';
2059
2543
  },
2060
2544
 
2061
2545
  zoneName : function () {
2062
- return this._isUTC ? "Coordinated Universal Time" : "";
2546
+ return this._isUTC ? 'Coordinated Universal Time' : '';
2063
2547
  },
2064
2548
 
2065
2549
  parseZone : function () {
2066
2550
  if (this._tzm) {
2067
- this.zone(this._tzm);
2551
+ this.utcOffset(this._tzm);
2068
2552
  } else if (typeof this._i === 'string') {
2069
- this.zone(this._i);
2553
+ this.utcOffset(utcOffsetFromString(this._i));
2070
2554
  }
2071
2555
  return this;
2072
2556
  },
@@ -2076,10 +2560,10 @@
2076
2560
  input = 0;
2077
2561
  }
2078
2562
  else {
2079
- input = moment(input).zone();
2563
+ input = moment(input).utcOffset();
2080
2564
  }
2081
2565
 
2082
- return (this.zone() - input) % 60 === 0;
2566
+ return (this.utcOffset() - input) % 60 === 0;
2083
2567
  },
2084
2568
 
2085
2569
  daysInMonth : function () {
@@ -2088,36 +2572,36 @@
2088
2572
 
2089
2573
  dayOfYear : function (input) {
2090
2574
  var dayOfYear = round((moment(this).startOf('day') - moment(this).startOf('year')) / 864e5) + 1;
2091
- return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
2575
+ return input == null ? dayOfYear : this.add((input - dayOfYear), 'd');
2092
2576
  },
2093
2577
 
2094
- quarter : function () {
2095
- return Math.ceil((this.month() + 1.0) / 3.0);
2578
+ quarter : function (input) {
2579
+ return input == null ? Math.ceil((this.month() + 1) / 3) : this.month((input - 1) * 3 + this.month() % 3);
2096
2580
  },
2097
2581
 
2098
2582
  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));
2583
+ var year = weekOfYear(this, this.localeData()._week.dow, this.localeData()._week.doy).year;
2584
+ return input == null ? year : this.add((input - year), 'y');
2101
2585
  },
2102
2586
 
2103
2587
  isoWeekYear : function (input) {
2104
2588
  var year = weekOfYear(this, 1, 4).year;
2105
- return input == null ? year : this.add("y", (input - year));
2589
+ return input == null ? year : this.add((input - year), 'y');
2106
2590
  },
2107
2591
 
2108
2592
  week : function (input) {
2109
- var week = this.lang().week(this);
2110
- return input == null ? week : this.add("d", (input - week) * 7);
2593
+ var week = this.localeData().week(this);
2594
+ return input == null ? week : this.add((input - week) * 7, 'd');
2111
2595
  },
2112
2596
 
2113
2597
  isoWeek : function (input) {
2114
2598
  var week = weekOfYear(this, 1, 4).week;
2115
- return input == null ? week : this.add("d", (input - week) * 7);
2599
+ return input == null ? week : this.add((input - week) * 7, 'd');
2116
2600
  },
2117
2601
 
2118
2602
  weekday : function (input) {
2119
- var weekday = (this.day() + 7 - this.lang()._week.dow) % 7;
2120
- return input == null ? weekday : this.add("d", input - weekday);
2603
+ var weekday = (this.day() + 7 - this.localeData()._week.dow) % 7;
2604
+ return input == null ? weekday : this.add(input - weekday, 'd');
2121
2605
  },
2122
2606
 
2123
2607
  isoWeekday : function (input) {
@@ -2127,68 +2611,161 @@
2127
2611
  return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
2128
2612
  },
2129
2613
 
2614
+ isoWeeksInYear : function () {
2615
+ return weeksInYear(this.year(), 1, 4);
2616
+ },
2617
+
2618
+ weeksInYear : function () {
2619
+ var weekInfo = this.localeData()._week;
2620
+ return weeksInYear(this.year(), weekInfo.dow, weekInfo.doy);
2621
+ },
2622
+
2130
2623
  get : function (units) {
2131
2624
  units = normalizeUnits(units);
2132
2625
  return this[units]();
2133
2626
  },
2134
2627
 
2135
2628
  set : function (units, value) {
2136
- units = normalizeUnits(units);
2137
- if (typeof this[units] === 'function') {
2138
- this[units](value);
2629
+ var unit;
2630
+ if (typeof units === 'object') {
2631
+ for (unit in units) {
2632
+ this.set(unit, units[unit]);
2633
+ }
2634
+ }
2635
+ else {
2636
+ units = normalizeUnits(units);
2637
+ if (typeof this[units] === 'function') {
2638
+ this[units](value);
2639
+ }
2139
2640
  }
2140
2641
  return this;
2141
2642
  },
2142
2643
 
2143
- // If passed a language key, it will set the language for this
2144
- // instance. Otherwise, it will return the language configuration
2644
+ // If passed a locale key, it will set the locale for this
2645
+ // instance. Otherwise, it will return the locale configuration
2145
2646
  // variables for this instance.
2146
- lang : function (key) {
2647
+ locale : function (key) {
2648
+ var newLocaleData;
2649
+
2147
2650
  if (key === undefined) {
2148
- return this._lang;
2651
+ return this._locale._abbr;
2149
2652
  } else {
2150
- this._lang = getLangDefinition(key);
2653
+ newLocaleData = moment.localeData(key);
2654
+ if (newLocaleData != null) {
2655
+ this._locale = newLocaleData;
2656
+ }
2151
2657
  return this;
2152
2658
  }
2659
+ },
2660
+
2661
+ lang : deprecate(
2662
+ 'moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.',
2663
+ function (key) {
2664
+ if (key === undefined) {
2665
+ return this.localeData();
2666
+ } else {
2667
+ return this.locale(key);
2668
+ }
2669
+ }
2670
+ ),
2671
+
2672
+ localeData : function () {
2673
+ return this._locale;
2674
+ },
2675
+
2676
+ _dateUtcOffset : function () {
2677
+ // On Firefox.24 Date#getTimezoneOffset returns a floating point.
2678
+ // https://github.com/moment/moment/pull/1871
2679
+ return -Math.round(this._d.getTimezoneOffset() / 15) * 15;
2153
2680
  }
2681
+
2154
2682
  });
2155
2683
 
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);
2684
+ function rawMonthSetter(mom, value) {
2685
+ var dayOfMonth;
2686
+
2687
+ // TODO: Move this out of here!
2688
+ if (typeof value === 'string') {
2689
+ value = mom.localeData().monthsParse(value);
2690
+ // TODO: Another silent failure?
2691
+ if (typeof value !== 'number') {
2692
+ return mom;
2693
+ }
2694
+ }
2695
+
2696
+ dayOfMonth = Math.min(mom.date(),
2697
+ daysInMonth(mom.year(), value));
2698
+ mom._d['set' + (mom._isUTC ? 'UTC' : '') + 'Month'](value, dayOfMonth);
2699
+ return mom;
2700
+ }
2701
+
2702
+ function rawGetter(mom, unit) {
2703
+ return mom._d['get' + (mom._isUTC ? 'UTC' : '') + unit]();
2704
+ }
2705
+
2706
+ function rawSetter(mom, unit, value) {
2707
+ if (unit === 'Month') {
2708
+ return rawMonthSetter(mom, value);
2709
+ } else {
2710
+ return mom._d['set' + (mom._isUTC ? 'UTC' : '') + unit](value);
2711
+ }
2712
+ }
2713
+
2714
+ function makeAccessor(unit, keepTime) {
2715
+ return function (value) {
2716
+ if (value != null) {
2717
+ rawSetter(this, unit, value);
2718
+ moment.updateOffset(this, keepTime);
2163
2719
  return this;
2164
2720
  } else {
2165
- return this._d['get' + utc + key]();
2721
+ return rawGetter(this, unit);
2166
2722
  }
2167
2723
  };
2168
2724
  }
2169
2725
 
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');
2726
+ moment.fn.millisecond = moment.fn.milliseconds = makeAccessor('Milliseconds', false);
2727
+ moment.fn.second = moment.fn.seconds = makeAccessor('Seconds', false);
2728
+ moment.fn.minute = moment.fn.minutes = makeAccessor('Minutes', false);
2729
+ // Setting the hour should keep the time, because the user explicitly
2730
+ // specified which hour he wants. So trying to maintain the same hour (in
2731
+ // a new timezone) makes sense. Adding/subtracting hours does not follow
2732
+ // this rule.
2733
+ moment.fn.hour = moment.fn.hours = makeAccessor('Hours', true);
2734
+ // moment.fn.month is defined separately
2735
+ moment.fn.date = makeAccessor('Date', true);
2736
+ moment.fn.dates = deprecate('dates accessor is deprecated. Use date instead.', makeAccessor('Date', true));
2737
+ moment.fn.year = makeAccessor('FullYear', true);
2738
+ moment.fn.years = deprecate('years accessor is deprecated. Use year instead.', makeAccessor('FullYear', true));
2177
2739
 
2178
2740
  // add plural methods
2179
2741
  moment.fn.days = moment.fn.day;
2180
2742
  moment.fn.months = moment.fn.month;
2181
2743
  moment.fn.weeks = moment.fn.week;
2182
2744
  moment.fn.isoWeeks = moment.fn.isoWeek;
2745
+ moment.fn.quarters = moment.fn.quarter;
2183
2746
 
2184
2747
  // add aliased format methods
2185
2748
  moment.fn.toJSON = moment.fn.toISOString;
2186
2749
 
2750
+ // alias isUtc for dev-friendliness
2751
+ moment.fn.isUTC = moment.fn.isUtc;
2752
+
2187
2753
  /************************************
2188
2754
  Duration Prototype
2189
2755
  ************************************/
2190
2756
 
2191
2757
 
2758
+ function daysToYears (days) {
2759
+ // 400 years have 146097 days (taking into account leap year rules)
2760
+ return days * 400 / 146097;
2761
+ }
2762
+
2763
+ function yearsToDays (years) {
2764
+ // years * 365 + absRound(years / 4) -
2765
+ // absRound(years / 100) + absRound(years / 400);
2766
+ return years * 146097 / 400;
2767
+ }
2768
+
2192
2769
  extend(moment.duration.fn = Duration.prototype, {
2193
2770
 
2194
2771
  _bubble : function () {
@@ -2196,7 +2773,7 @@
2196
2773
  days = this._days,
2197
2774
  months = this._months,
2198
2775
  data = this._data,
2199
- seconds, minutes, hours, years;
2776
+ seconds, minutes, hours, years = 0;
2200
2777
 
2201
2778
  // The following code bubbles up values, see the tests for
2202
2779
  // examples of what that means.
@@ -2212,15 +2789,40 @@
2212
2789
  data.hours = hours % 24;
2213
2790
 
2214
2791
  days += absRound(hours / 24);
2215
- data.days = days % 30;
2216
2792
 
2793
+ // Accurately convert days to years, assume start from year 0.
2794
+ years = absRound(daysToYears(days));
2795
+ days -= absRound(yearsToDays(years));
2796
+
2797
+ // 30 days to a month
2798
+ // TODO (iskren): Use anchor date (like 1st Jan) to compute this.
2217
2799
  months += absRound(days / 30);
2218
- data.months = months % 12;
2800
+ days %= 30;
2801
+
2802
+ // 12 months -> 1 year
2803
+ years += absRound(months / 12);
2804
+ months %= 12;
2219
2805
 
2220
- years = absRound(months / 12);
2806
+ data.days = days;
2807
+ data.months = months;
2221
2808
  data.years = years;
2222
2809
  },
2223
2810
 
2811
+ abs : function () {
2812
+ this._milliseconds = Math.abs(this._milliseconds);
2813
+ this._days = Math.abs(this._days);
2814
+ this._months = Math.abs(this._months);
2815
+
2816
+ this._data.milliseconds = Math.abs(this._data.milliseconds);
2817
+ this._data.seconds = Math.abs(this._data.seconds);
2818
+ this._data.minutes = Math.abs(this._data.minutes);
2819
+ this._data.hours = Math.abs(this._data.hours);
2820
+ this._data.months = Math.abs(this._data.months);
2821
+ this._data.years = Math.abs(this._data.years);
2822
+
2823
+ return this;
2824
+ },
2825
+
2224
2826
  weeks : function () {
2225
2827
  return absRound(this.days() / 7);
2226
2828
  },
@@ -2233,14 +2835,13 @@
2233
2835
  },
2234
2836
 
2235
2837
  humanize : function (withSuffix) {
2236
- var difference = +this,
2237
- output = relativeTime(difference, !withSuffix, this.lang());
2838
+ var output = relativeTime(this, !withSuffix, this.localeData());
2238
2839
 
2239
2840
  if (withSuffix) {
2240
- output = this.lang().pastFuture(difference, output);
2841
+ output = this.localeData().pastFuture(+this, output);
2241
2842
  }
2242
2843
 
2243
- return this.lang().postformat(output);
2844
+ return this.localeData().postformat(output);
2244
2845
  },
2245
2846
 
2246
2847
  add : function (input, val) {
@@ -2274,13 +2875,41 @@
2274
2875
  },
2275
2876
 
2276
2877
  as : function (units) {
2878
+ var days, months;
2277
2879
  units = normalizeUnits(units);
2278
- return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
2880
+
2881
+ if (units === 'month' || units === 'year') {
2882
+ days = this._days + this._milliseconds / 864e5;
2883
+ months = this._months + daysToYears(days) * 12;
2884
+ return units === 'month' ? months : months / 12;
2885
+ } else {
2886
+ // handle milliseconds separately because of floating point math errors (issue #1867)
2887
+ days = this._days + Math.round(yearsToDays(this._months / 12));
2888
+ switch (units) {
2889
+ case 'week': return days / 7 + this._milliseconds / 6048e5;
2890
+ case 'day': return days + this._milliseconds / 864e5;
2891
+ case 'hour': return days * 24 + this._milliseconds / 36e5;
2892
+ case 'minute': return days * 24 * 60 + this._milliseconds / 6e4;
2893
+ case 'second': return days * 24 * 60 * 60 + this._milliseconds / 1000;
2894
+ // Math.floor prevents floating point math errors here
2895
+ case 'millisecond': return Math.floor(days * 24 * 60 * 60 * 1000) + this._milliseconds;
2896
+ default: throw new Error('Unknown unit ' + units);
2897
+ }
2898
+ }
2279
2899
  },
2280
2900
 
2281
2901
  lang : moment.fn.lang,
2902
+ locale : moment.fn.locale,
2903
+
2904
+ toIsoString : deprecate(
2905
+ 'toIsoString() is deprecated. Please use toISOString() instead ' +
2906
+ '(notice the capitals)',
2907
+ function () {
2908
+ return this.toISOString();
2909
+ }
2910
+ ),
2282
2911
 
2283
- toIsoString : function () {
2912
+ toISOString : function () {
2284
2913
  // inspired by https://github.com/dordille/moment-isoduration/blob/master/moment.isoduration.js
2285
2914
  var years = Math.abs(this.years()),
2286
2915
  months = Math.abs(this.months()),
@@ -2304,41 +2933,64 @@
2304
2933
  (hours ? hours + 'H' : '') +
2305
2934
  (minutes ? minutes + 'M' : '') +
2306
2935
  (seconds ? seconds + 'S' : '');
2936
+ },
2937
+
2938
+ localeData : function () {
2939
+ return this._locale;
2940
+ },
2941
+
2942
+ toJSON : function () {
2943
+ return this.toISOString();
2307
2944
  }
2308
2945
  });
2309
2946
 
2947
+ moment.duration.fn.toString = moment.duration.fn.toISOString;
2948
+
2310
2949
  function makeDurationGetter(name) {
2311
2950
  moment.duration.fn[name] = function () {
2312
2951
  return this._data[name];
2313
2952
  };
2314
2953
  }
2315
2954
 
2316
- function makeDurationAsGetter(name, factor) {
2317
- moment.duration.fn['as' + name] = function () {
2318
- return +this / factor;
2319
- };
2320
- }
2321
-
2322
2955
  for (i in unitMillisecondFactors) {
2323
- if (unitMillisecondFactors.hasOwnProperty(i)) {
2324
- makeDurationAsGetter(i, unitMillisecondFactors[i]);
2956
+ if (hasOwnProp(unitMillisecondFactors, i)) {
2325
2957
  makeDurationGetter(i.toLowerCase());
2326
2958
  }
2327
2959
  }
2328
2960
 
2329
- makeDurationAsGetter('Weeks', 6048e5);
2961
+ moment.duration.fn.asMilliseconds = function () {
2962
+ return this.as('ms');
2963
+ };
2964
+ moment.duration.fn.asSeconds = function () {
2965
+ return this.as('s');
2966
+ };
2967
+ moment.duration.fn.asMinutes = function () {
2968
+ return this.as('m');
2969
+ };
2970
+ moment.duration.fn.asHours = function () {
2971
+ return this.as('h');
2972
+ };
2973
+ moment.duration.fn.asDays = function () {
2974
+ return this.as('d');
2975
+ };
2976
+ moment.duration.fn.asWeeks = function () {
2977
+ return this.as('weeks');
2978
+ };
2330
2979
  moment.duration.fn.asMonths = function () {
2331
- return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
2980
+ return this.as('M');
2981
+ };
2982
+ moment.duration.fn.asYears = function () {
2983
+ return this.as('y');
2332
2984
  };
2333
-
2334
2985
 
2335
2986
  /************************************
2336
- Default Lang
2987
+ Default Locale
2337
2988
  ************************************/
2338
2989
 
2339
2990
 
2340
- // Set default language, other languages will inherit from English.
2341
- moment.lang('en', {
2991
+ // Set default locale, other locale will inherit from English.
2992
+ moment.locale('en', {
2993
+ ordinalParse: /\d{1,2}(th|st|nd|rd)/,
2342
2994
  ordinal : function (number) {
2343
2995
  var b = number % 10,
2344
2996
  output = (toInt(number % 100 / 10) === 1) ? 'th' :
@@ -2349,51 +3001,42 @@
2349
3001
  }
2350
3002
  });
2351
3003
 
2352
- /* EMBED_LANGUAGES */
3004
+ /* EMBED_LOCALES */
2353
3005
 
2354
3006
  /************************************
2355
3007
  Exposing Moment
2356
3008
  ************************************/
2357
3009
 
2358
- function makeGlobal(deprecate) {
2359
- var warned = false, local_moment = moment;
3010
+ function makeGlobal(shouldDeprecate) {
2360
3011
  /*global ender:false */
2361
3012
  if (typeof ender !== 'undefined') {
2362
3013
  return;
2363
3014
  }
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);
3015
+ oldGlobalMoment = globalScope.moment;
3016
+ if (shouldDeprecate) {
3017
+ globalScope.moment = deprecate(
3018
+ 'Accessing Moment through the global scope is ' +
3019
+ 'deprecated, and will be removed in an upcoming ' +
3020
+ 'release.',
3021
+ moment);
2379
3022
  } else {
2380
- global['moment'] = moment;
3023
+ globalScope.moment = moment;
2381
3024
  }
2382
3025
  }
2383
3026
 
2384
3027
  // CommonJS module is defined
2385
3028
  if (hasModule) {
2386
3029
  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);
3030
+ } else if (typeof define === 'function' && define.amd) {
3031
+ define(function (require, exports, module) {
3032
+ if (module.config && module.config() && module.config().noGlobal === true) {
3033
+ // release the global variable
3034
+ globalScope.moment = oldGlobalMoment;
2393
3035
  }
2394
3036
 
2395
3037
  return moment;
2396
3038
  });
3039
+ makeGlobal(true);
2397
3040
  } else {
2398
3041
  makeGlobal();
2399
3042
  }