momentjs-rails 2.0.0.2 → 2.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (64) hide show
  1. checksums.yaml +7 -0
  2. data/news.md +4 -0
  3. data/test/dummy/log/test.log +14 -0
  4. data/test/dummy/tmp/cache/assets/D1C/680/sprockets%2F16ed4d5afdb2919596e6f8790e2116c2 +0 -0
  5. data/test/dummy/tmp/cache/assets/D35/CA0/sprockets%2F493e64bce2d302801dc01cf7cd096a58 +0 -0
  6. data/test/dummy/tmp/cache/assets/D3F/5F0/sprockets%2F4a6c53eae7c6e41a69a191578bbb6417 +0 -0
  7. data/test/dummy/tmp/cache/assets/D58/BD0/sprockets%2F4de9ddc9b725c715a54c98697b2528fe +0 -0
  8. data/test/dummy/tmp/cache/assets/D75/510/sprockets%2Fe690787ac522f47a6be024bfcc1767ee +0 -0
  9. data/test/dummy/tmp/cache/assets/E10/250/sprockets%2Fe4badb9ddfda484eb9671bf88567be61 +0 -0
  10. data/test/integration/navigation_test.rb +1 -1
  11. data/vendor/assets/javascripts/moment.js +380 -118
  12. data/vendor/assets/javascripts/moment/ar-ma.js +1 -42
  13. data/vendor/assets/javascripts/moment/ar.js +2 -42
  14. data/vendor/assets/javascripts/moment/bg.js +1 -73
  15. data/vendor/assets/javascripts/moment/br.js +4 -0
  16. data/vendor/assets/javascripts/moment/ca.js +1 -53
  17. data/vendor/assets/javascripts/moment/cs.js +1 -142
  18. data/vendor/assets/javascripts/moment/cv.js +1 -47
  19. data/vendor/assets/javascripts/moment/da.js +1 -43
  20. data/vendor/assets/javascripts/moment/de.js +2 -43
  21. data/vendor/assets/javascripts/moment/el.js +4 -0
  22. data/vendor/assets/javascripts/moment/en-ca.js +1 -46
  23. data/vendor/assets/javascripts/moment/en-gb.js +1 -50
  24. data/vendor/assets/javascripts/moment/eo.js +1 -50
  25. data/vendor/assets/javascripts/moment/es.js +1 -53
  26. data/vendor/assets/javascripts/moment/et.js +1 -47
  27. data/vendor/assets/javascripts/moment/eu.js +1 -47
  28. data/vendor/assets/javascripts/moment/fa.js +4 -0
  29. data/vendor/assets/javascripts/moment/fi.js +1 -90
  30. data/vendor/assets/javascripts/moment/fr-ca.js +1 -41
  31. data/vendor/assets/javascripts/moment/fr.js +1 -45
  32. data/vendor/assets/javascripts/moment/gl.js +1 -53
  33. data/vendor/assets/javascripts/moment/he.js +1 -42
  34. data/vendor/assets/javascripts/moment/hi.js +4 -0
  35. data/vendor/assets/javascripts/moment/hu.js +1 -84
  36. data/vendor/assets/javascripts/moment/id.js +1 -53
  37. data/vendor/assets/javascripts/moment/is.js +1 -111
  38. data/vendor/assets/javascripts/moment/it.js +2 -43
  39. data/vendor/assets/javascripts/moment/ja.js +1 -45
  40. data/vendor/assets/javascripts/moment/ka.js +4 -0
  41. data/vendor/assets/javascripts/moment/ko.js +1 -43
  42. data/vendor/assets/javascripts/moment/lv.js +1 -64
  43. data/vendor/assets/javascripts/moment/ms-my.js +4 -0
  44. data/vendor/assets/javascripts/moment/nb.js +1 -43
  45. data/vendor/assets/javascripts/moment/ne.js +1 -92
  46. data/vendor/assets/javascripts/moment/nl.js +1 -54
  47. data/vendor/assets/javascripts/moment/nn.js +4 -0
  48. data/vendor/assets/javascripts/moment/pl.js +1 -76
  49. data/vendor/assets/javascripts/moment/pt-br.js +1 -43
  50. data/vendor/assets/javascripts/moment/pt.js +1 -47
  51. data/vendor/assets/javascripts/moment/ro.js +1 -42
  52. data/vendor/assets/javascripts/moment/ru.js +2 -121
  53. data/vendor/assets/javascripts/moment/sk.js +5 -0
  54. data/vendor/assets/javascripts/moment/sl.js +1 -131
  55. data/vendor/assets/javascripts/moment/sq.js +5 -0
  56. data/vendor/assets/javascripts/moment/sv.js +1 -50
  57. data/vendor/assets/javascripts/moment/th.js +1 -45
  58. data/vendor/assets/javascripts/moment/tr.js +1 -78
  59. data/vendor/assets/javascripts/moment/tzm-la.js +1 -42
  60. data/vendor/assets/javascripts/moment/tzm.js +1 -42
  61. data/vendor/assets/javascripts/moment/uk.js +2 -119
  62. data/vendor/assets/javascripts/moment/zh-cn.js +1 -55
  63. data/vendor/assets/javascripts/moment/zh-tw.js +1 -55
  64. metadata +21 -24
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 788e8f0c378d64f7f40aae1e04f5de7fab3c1685
4
+ data.tar.gz: 572ec979e2915e8329a84690369118eb7760fe15
5
+ SHA512:
6
+ metadata.gz: 09363f5b9f8fd522e9dd507bfc1f88a2f3da3d2ccf1ff9e0edf4561f8d5eded8578c1f96f5286666acc91d8db709bc15a63dfcd2884002ee7747234dce752de0
7
+ data.tar.gz: 7b05e42bf3cb91d45c06e299038ec473c6293aed453fa5ad370391a40f17fe0d3ab4c9e4117693e45f8bba5e5246a414f7c57dccd138d2ad1f0c73945c5794fe
data/news.md CHANGED
@@ -1,3 +1,7 @@
1
+ ### Version 2.1.0 (2013-07-20)
2
+ - Updated to Moment.js to 2.1.0
3
+ - Updated localization files using compressed versions (ready for browser)
4
+
1
5
  ### Version 2.0.0.2 (2013-06-06)
2
6
  - Fix localization files (thanks, eddloschi).
3
7
 
@@ -129,3 +129,17 @@ Compiled moment/fr.js (0ms) (pid 73048)
129
129
  Served asset /moment/fr.js - 200 OK (28ms)
130
130
  Started GET "/assets/moment.js" for 127.0.0.1 at 2013-06-06 21:49:55 -0400
131
131
  Served asset /moment.js - 200 OK (0ms)
132
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:00:25 -0400
133
+ Compiled moment.js (0ms) (pid 5373)
134
+ Served asset /moment.js - 200 OK (75ms)
135
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-07-20 10:00:25 -0400
136
+ Compiled moment/fr.js (0ms) (pid 5373)
137
+ Served asset /moment/fr.js - 200 OK (96ms)
138
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:00:25 -0400
139
+ Served asset /moment.js - 200 OK (0ms)
140
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:01:19 -0400
141
+ Served asset /moment.js - 200 OK (2ms)
142
+ Started GET "/assets/moment/fr.js" for 127.0.0.1 at 2013-07-20 10:01:19 -0400
143
+ Served asset /moment/fr.js - 200 OK (1ms)
144
+ Started GET "/assets/moment.js" for 127.0.0.1 at 2013-07-20 10:01:19 -0400
145
+ Served asset /moment.js - 200 OK (0ms)
@@ -8,7 +8,7 @@ class NavigationTest < ActionDispatch::IntegrationTest
8
8
 
9
9
  test 'momentjs response is for the expected version' do
10
10
  get 'assets/moment.js'
11
- assert_match(/VERSION = "2\.0\.0"/, @response.body)
11
+ assert_match(/VERSION = "2\.1\.0"/, @response.body)
12
12
  end
13
13
 
14
14
  test 'can access momentjs translation' do
@@ -1,5 +1,5 @@
1
1
  // moment.js
2
- // version : 2.0.0
2
+ // version : 2.1.0
3
3
  // author : Tim Wood
4
4
  // license : MIT
5
5
  // momentjs.com
@@ -11,7 +11,7 @@
11
11
  ************************************/
12
12
 
13
13
  var moment,
14
- VERSION = "2.0.0",
14
+ VERSION = "2.1.0",
15
15
  round = Math.round, i,
16
16
  // internal storage for language config files
17
17
  languages = {},
@@ -21,21 +21,19 @@
21
21
 
22
22
  // ASP.NET json date format regex
23
23
  aspNetJsonRegex = /^\/?Date\((\-?\d+)/i,
24
+ aspNetTimeSpanJsonRegex = /(\-)?(\d*)?\.?(\d+)\:(\d+)\:(\d+)\.?(\d{3})?/,
24
25
 
25
26
  // format tokens
26
- formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,
27
+ formattingTokens = /(\[[^\[]*\])|(\\)?(Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|YYYYY|YYYY|YY|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|mm?|ss?|SS?S?|X|zz?|ZZ?|.)/g,
27
28
  localFormattingTokens = /(\[[^\[]*\])|(\\)?(LT|LL?L?L?|l{1,4})/g,
28
29
 
29
- // parsing tokens
30
- parseMultipleFormatChunker = /([0-9a-zA-Z\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+)/gi,
31
-
32
30
  // parsing token regexes
33
31
  parseTokenOneOrTwoDigits = /\d\d?/, // 0 - 99
34
32
  parseTokenOneToThreeDigits = /\d{1,3}/, // 0 - 999
35
33
  parseTokenThreeDigits = /\d{3}/, // 000 - 999
36
34
  parseTokenFourDigits = /\d{1,4}/, // 0 - 9999
37
35
  parseTokenSixDigits = /[+\-]?\d{1,6}/, // -999,999 - 999,999
38
- parseTokenWord = /[0-9]*[a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+|[\u0600-\u06FF]+\s*?[\u0600-\u06FF]+/i, // any word (or two) characters or numbers including two word month in arabic.
36
+ 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.
39
37
  parseTokenTimezone = /Z|[\+\-]\d\d:?\d\d/i, // +00:00 -00:00 +0000 -0000 or Z
40
38
  parseTokenT = /T/i, // T (ISO seperator)
41
39
  parseTokenTimestampMs = /[\+\-]?\d+(\.\d{1,3})?/, // 123456789 123456789.123
@@ -57,7 +55,7 @@
57
55
  parseTimezoneChunker = /([\+\-]|\d\d)/gi,
58
56
 
59
57
  // getter and setter names
60
- proxyGettersAndSetters = 'Month|Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
58
+ proxyGettersAndSetters = 'Date|Hours|Minutes|Seconds|Milliseconds'.split('|'),
61
59
  unitMillisecondFactors = {
62
60
  'Milliseconds' : 1,
63
61
  'Seconds' : 1e3,
@@ -68,6 +66,17 @@
68
66
  'Years' : 31536e6
69
67
  },
70
68
 
69
+ unitAliases = {
70
+ ms : 'millisecond',
71
+ s : 'second',
72
+ m : 'minute',
73
+ h : 'hour',
74
+ d : 'day',
75
+ w : 'week',
76
+ M : 'month',
77
+ y : 'year'
78
+ },
79
+
71
80
  // format function strings
72
81
  formatFunctions = {},
73
82
 
@@ -118,6 +127,30 @@
118
127
  YYYYY : function () {
119
128
  return leftZeroFill(this.year(), 5);
120
129
  },
130
+ gg : function () {
131
+ return leftZeroFill(this.weekYear() % 100, 2);
132
+ },
133
+ gggg : function () {
134
+ return this.weekYear();
135
+ },
136
+ ggggg : function () {
137
+ return leftZeroFill(this.weekYear(), 5);
138
+ },
139
+ GG : function () {
140
+ return leftZeroFill(this.isoWeekYear() % 100, 2);
141
+ },
142
+ GGGG : function () {
143
+ return this.isoWeekYear();
144
+ },
145
+ GGGGG : function () {
146
+ return leftZeroFill(this.isoWeekYear(), 5);
147
+ },
148
+ e : function () {
149
+ return this.weekday();
150
+ },
151
+ E : function () {
152
+ return this.isoWeekday();
153
+ },
121
154
  a : function () {
122
155
  return this.lang().meridiem(this.hours(), this.minutes(), true);
123
156
  },
@@ -163,6 +196,12 @@
163
196
  }
164
197
  return b + leftZeroFill(~~(10 * a / 6), 4);
165
198
  },
199
+ z : function () {
200
+ return this.zoneAbbr();
201
+ },
202
+ zz : function () {
203
+ return this.zoneName();
204
+ },
166
205
  X : function () {
167
206
  return this.unix();
168
207
  }
@@ -173,15 +212,15 @@
173
212
  return leftZeroFill(func.call(this, a), count);
174
213
  };
175
214
  }
176
- function ordinalizeToken(func) {
215
+ function ordinalizeToken(func, period) {
177
216
  return function (a) {
178
- return this.lang().ordinal(func.call(this, a));
217
+ return this.lang().ordinal(func.call(this, a), period);
179
218
  };
180
219
  }
181
220
 
182
221
  while (ordinalizeTokens.length) {
183
222
  i = ordinalizeTokens.pop();
184
- formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i]);
223
+ formatTokenFunctions[i + 'o'] = ordinalizeToken(formatTokenFunctions[i], i);
185
224
  }
186
225
  while (paddedTokens.length) {
187
226
  i = paddedTokens.pop();
@@ -205,8 +244,7 @@
205
244
 
206
245
  // Duration Constructor
207
246
  function Duration(duration) {
208
- var data = this._data = {},
209
- years = duration.years || duration.year || duration.y || 0,
247
+ var years = duration.years || duration.year || duration.y || 0,
210
248
  months = duration.months || duration.month || duration.M || 0,
211
249
  weeks = duration.weeks || duration.week || duration.w || 0,
212
250
  days = duration.days || duration.day || duration.d || 0,
@@ -215,6 +253,9 @@
215
253
  seconds = duration.seconds || duration.second || duration.s || 0,
216
254
  milliseconds = duration.milliseconds || duration.millisecond || duration.ms || 0;
217
255
 
256
+ // store reference to input for deterministic cloning
257
+ this._input = duration;
258
+
218
259
  // representation for dateAddRemove
219
260
  this._milliseconds = milliseconds +
220
261
  seconds * 1e3 + // 1000
@@ -230,29 +271,9 @@
230
271
  this._months = months +
231
272
  years * 12;
232
273
 
233
- // The following code bubbles up values, see the tests for
234
- // examples of what that means.
235
- data.milliseconds = milliseconds % 1000;
236
- seconds += absRound(milliseconds / 1000);
237
-
238
- data.seconds = seconds % 60;
239
- minutes += absRound(seconds / 60);
240
-
241
- data.minutes = minutes % 60;
242
- hours += absRound(minutes / 60);
243
-
244
- data.hours = hours % 24;
245
- days += absRound(hours / 24);
274
+ this._data = {};
246
275
 
247
- days += weeks * 7;
248
- data.days = days % 30;
249
-
250
- months += absRound(days / 30);
251
-
252
- data.months = months % 12;
253
- years += absRound(months / 12);
254
-
255
- data.years = years;
276
+ this._bubble();
256
277
  }
257
278
 
258
279
 
@@ -289,23 +310,35 @@
289
310
  }
290
311
 
291
312
  // helper function for _.addTime and _.subtractTime
292
- function addOrSubtractDurationFromMoment(mom, duration, isAdding) {
293
- var ms = duration._milliseconds,
294
- d = duration._days,
295
- M = duration._months,
313
+ function addOrSubtractDurationFromMoment(mom, duration, isAdding, ignoreUpdateOffset) {
314
+ var milliseconds = duration._milliseconds,
315
+ days = duration._days,
316
+ months = duration._months,
317
+ minutes,
318
+ hours,
296
319
  currentDate;
297
320
 
298
- if (ms) {
299
- mom._d.setTime(+mom + ms * isAdding);
321
+ if (milliseconds) {
322
+ mom._d.setTime(+mom._d + milliseconds * isAdding);
323
+ }
324
+ // store the minutes and hours so we can restore them
325
+ if (days || months) {
326
+ minutes = mom.minute();
327
+ hours = mom.hour();
328
+ }
329
+ if (days) {
330
+ mom.date(mom.date() + days * isAdding);
300
331
  }
301
- if (d) {
302
- mom.date(mom.date() + d * isAdding);
332
+ if (months) {
333
+ mom.month(mom.month() + months * isAdding);
303
334
  }
304
- if (M) {
305
- currentDate = mom.date();
306
- mom.date(1)
307
- .month(mom.month() + M * isAdding)
308
- .date(Math.min(currentDate, mom.daysInMonth()));
335
+ if (milliseconds && !ignoreUpdateOffset) {
336
+ moment.updateOffset(mom);
337
+ }
338
+ // restore the minutes and hours after possibly changing dst
339
+ if (days || months) {
340
+ mom.minute(minutes);
341
+ mom.hour(hours);
309
342
  }
310
343
  }
311
344
 
@@ -328,6 +361,10 @@
328
361
  return diffs + lengthDiff;
329
362
  }
330
363
 
364
+ function normalizeUnits(units) {
365
+ return units ? unitAliases[units] || units.toLowerCase().replace(/(.)s$/, '$1') : units;
366
+ }
367
+
331
368
 
332
369
  /************************************
333
370
  Languages
@@ -358,7 +395,7 @@
358
395
  },
359
396
 
360
397
  monthsParse : function (monthName) {
361
- var i, mom, regex, output;
398
+ var i, mom, regex;
362
399
 
363
400
  if (!this._monthsParse) {
364
401
  this._monthsParse = [];
@@ -393,6 +430,27 @@
393
430
  return this._weekdaysMin[m.day()];
394
431
  },
395
432
 
433
+ weekdaysParse : function (weekdayName) {
434
+ var i, mom, regex;
435
+
436
+ if (!this._weekdaysParse) {
437
+ this._weekdaysParse = [];
438
+ }
439
+
440
+ for (i = 0; i < 7; i++) {
441
+ // make the regex if we don't have it already
442
+ if (!this._weekdaysParse[i]) {
443
+ mom = moment([2000, 1]).day(i);
444
+ regex = '^' + this.weekdays(mom, '') + '|^' + this.weekdaysShort(mom, '') + '|^' + this.weekdaysMin(mom, '');
445
+ this._weekdaysParse[i] = new RegExp(regex.replace('.', ''), 'i');
446
+ }
447
+ // test the regex
448
+ if (this._weekdaysParse[i].test(weekdayName)) {
449
+ return i;
450
+ }
451
+ }
452
+ },
453
+
396
454
  _longDateFormat : {
397
455
  LT : "h:mm A",
398
456
  L : "MM/DD/YYYY",
@@ -411,6 +469,11 @@
411
469
  return output;
412
470
  },
413
471
 
472
+ isPM : function (input) {
473
+ return ((input + '').toLowerCase()[0] === 'p');
474
+ },
475
+
476
+ _meridiemParse : /[ap]\.?m?\.?/i,
414
477
  meridiem : function (hours, minutes, isLower) {
415
478
  if (hours > 11) {
416
479
  return isLower ? 'pm' : 'PM';
@@ -424,7 +487,7 @@
424
487
  nextDay : '[Tomorrow at] LT',
425
488
  nextWeek : 'dddd [at] LT',
426
489
  lastDay : '[Yesterday at] LT',
427
- lastWeek : '[last] dddd [at] LT',
490
+ lastWeek : '[Last] dddd [at] LT',
428
491
  sameElse : 'L'
429
492
  },
430
493
  calendar : function (key, mom) {
@@ -472,7 +535,7 @@
472
535
  },
473
536
 
474
537
  week : function (mom) {
475
- return weekOfYear(mom, this._week.dow, this._week.doy);
538
+ return weekOfYear(mom, this._week.dow, this._week.doy).week;
476
539
  },
477
540
  _week : {
478
541
  dow : 0, // Sunday is the first day of the week.
@@ -504,7 +567,12 @@
504
567
  return moment.fn._lang;
505
568
  }
506
569
  if (!languages[key] && hasModule) {
507
- require('./lang/' + key);
570
+ try {
571
+ require('./lang/' + key);
572
+ } catch (e) {
573
+ // call with no params to set to default
574
+ return moment.fn._lang;
575
+ }
508
576
  }
509
577
  return languages[key];
510
578
  }
@@ -536,7 +604,7 @@
536
604
  return function (mom) {
537
605
  var output = "";
538
606
  for (i = 0; i < length; i++) {
539
- output += typeof array[i].call === 'function' ? array[i].call(mom, format) : array[i];
607
+ output += array[i] instanceof Function ? array[i].call(mom, format) : array[i];
540
608
  }
541
609
  return output;
542
610
  };
@@ -568,7 +636,7 @@
568
636
 
569
637
 
570
638
  // get the regex to find the next token
571
- function getParseRegexForToken(token) {
639
+ function getParseRegexForToken(token, config) {
572
640
  switch (token) {
573
641
  case 'DDDD':
574
642
  return parseTokenThreeDigits;
@@ -586,9 +654,10 @@
586
654
  case 'dd':
587
655
  case 'ddd':
588
656
  case 'dddd':
657
+ return parseTokenWord;
589
658
  case 'a':
590
659
  case 'A':
591
- return parseTokenWord;
660
+ return getLangDefinition(config._l)._meridiemParse;
592
661
  case 'X':
593
662
  return parseTokenTimestampMs;
594
663
  case 'Z':
@@ -616,10 +685,17 @@
616
685
  }
617
686
  }
618
687
 
688
+ function timezoneMinutesFromString(string) {
689
+ var tzchunk = (parseTokenTimezone.exec(string) || [])[0],
690
+ parts = (tzchunk + '').match(parseTimezoneChunker) || ['-', 0, 0],
691
+ minutes = +(parts[1] * 60) + ~~parts[2];
692
+
693
+ return parts[0] === '+' ? -minutes : minutes;
694
+ }
695
+
619
696
  // function to convert string input to date
620
697
  function addTimeToArrayFromToken(token, input, config) {
621
- var a, b,
622
- datePartArray = config._a;
698
+ var a, datePartArray = config._a;
623
699
 
624
700
  switch (token) {
625
701
  // MONTH
@@ -657,7 +733,7 @@
657
733
  // AM / PM
658
734
  case 'a' : // fall through to A
659
735
  case 'A' :
660
- config._isPm = ((input + '').toLowerCase() === 'pm');
736
+ config._isPm = getLangDefinition(config._l).isPM(input);
661
737
  break;
662
738
  // 24 HOUR
663
739
  case 'H' : // fall through to hh
@@ -690,18 +766,7 @@
690
766
  case 'Z' : // fall through to ZZ
691
767
  case 'ZZ' :
692
768
  config._useUTC = true;
693
- a = (input + '').match(parseTimezoneChunker);
694
- if (a && a[1]) {
695
- config._tzh = ~~a[1];
696
- }
697
- if (a && a[2]) {
698
- config._tzm = ~~a[2];
699
- }
700
- // reverse offsets
701
- if (a && a[0] === '+') {
702
- config._tzh = -config._tzh;
703
- config._tzm = -config._tzm;
704
- }
769
+ config._tzm = timezoneMinutesFromString(input);
705
770
  break;
706
771
  }
707
772
 
@@ -727,8 +792,8 @@
727
792
  }
728
793
 
729
794
  // add the offsets to the time to be parsed so that we can have a clean array for checking isValid
730
- input[3] += config._tzh || 0;
731
- input[4] += config._tzm || 0;
795
+ input[3] += ~~((config._tzm || 0) / 60);
796
+ input[4] += ~~((config._tzm || 0) % 60);
732
797
 
733
798
  date = new Date(0);
734
799
 
@@ -753,7 +818,7 @@
753
818
  config._a = [];
754
819
 
755
820
  for (i = 0; i < tokens.length; i++) {
756
- parsedInput = (getParseRegexForToken(tokens[i]).exec(string) || [])[0];
821
+ parsedInput = (getParseRegexForToken(tokens[i], config).exec(string) || [])[0];
757
822
  if (parsedInput) {
758
823
  string = string.slice(string.indexOf(parsedInput) + parsedInput.length);
759
824
  }
@@ -762,6 +827,12 @@
762
827
  addTimeToArrayFromToken(tokens[i], parsedInput, config);
763
828
  }
764
829
  }
830
+
831
+ // add remaining unparsed input to the string
832
+ if (string) {
833
+ config._il = string;
834
+ }
835
+
765
836
  // handle am pm
766
837
  if (config._isPm && config._a[3] < 12) {
767
838
  config._a[3] += 12;
@@ -782,22 +853,22 @@
782
853
 
783
854
  scoreToBeat = 99,
784
855
  i,
785
- currentDate,
786
856
  currentScore;
787
857
 
788
- while (config._f.length) {
858
+ for (i = 0; i < config._f.length; i++) {
789
859
  tempConfig = extend({}, config);
790
- tempConfig._f = config._f.pop();
860
+ tempConfig._f = config._f[i];
791
861
  makeDateFromStringAndFormat(tempConfig);
792
862
  tempMoment = new Moment(tempConfig);
793
863
 
794
- if (tempMoment.isValid()) {
795
- bestMoment = tempMoment;
796
- break;
797
- }
798
-
799
864
  currentScore = compareArrays(tempConfig._a, tempMoment.toArray());
800
865
 
866
+ // if there is any input that was not parsed
867
+ // add a penalty for that format
868
+ if (tempMoment._il) {
869
+ currentScore += tempMoment._il.length;
870
+ }
871
+
801
872
  if (currentScore < scoreToBeat) {
802
873
  scoreToBeat = currentScore;
803
874
  bestMoment = tempMoment;
@@ -810,9 +881,12 @@
810
881
  // date from iso format
811
882
  function makeDateFromString(config) {
812
883
  var i,
813
- string = config._i;
814
- if (isoRegex.exec(string)) {
815
- config._f = 'YYYY-MM-DDT';
884
+ string = config._i,
885
+ match = isoRegex.exec(string);
886
+
887
+ if (match) {
888
+ // match[2] should be "T" or undefined
889
+ config._f = 'YYYY-MM-DD' + (match[2] || " ");
816
890
  for (i = 0; i < 4; i++) {
817
891
  if (isoTimes[i][1].exec(string)) {
818
892
  config._f += isoTimes[i][0];
@@ -894,7 +968,8 @@
894
968
  // (eg. ISO weeks use thursday (4))
895
969
  function weekOfYear(mom, firstDayOfWeek, firstDayOfWeekOfYear) {
896
970
  var end = firstDayOfWeekOfYear - firstDayOfWeek,
897
- daysToDayOfWeek = firstDayOfWeekOfYear - mom.day();
971
+ daysToDayOfWeek = firstDayOfWeekOfYear - mom.day(),
972
+ adjustedMoment;
898
973
 
899
974
 
900
975
  if (daysToDayOfWeek > end) {
@@ -905,7 +980,11 @@
905
980
  daysToDayOfWeek += 7;
906
981
  }
907
982
 
908
- return Math.ceil(moment(mom).add('d', daysToDayOfWeek).dayOfYear() / 7);
983
+ adjustedMoment = moment(mom).add('d', daysToDayOfWeek);
984
+ return {
985
+ week: Math.ceil(adjustedMoment.dayOfYear() / 7),
986
+ year: adjustedMoment.year()
987
+ };
909
988
  }
910
989
 
911
990
 
@@ -970,7 +1049,9 @@
970
1049
  moment.duration = function (input, key) {
971
1050
  var isDuration = moment.isDuration(input),
972
1051
  isNumber = (typeof input === 'number'),
973
- duration = (isDuration ? input._data : (isNumber ? {} : input)),
1052
+ duration = (isDuration ? input._input : (isNumber ? {} : input)),
1053
+ matched = aspNetTimeSpanJsonRegex.exec(input),
1054
+ sign,
974
1055
  ret;
975
1056
 
976
1057
  if (isNumber) {
@@ -979,6 +1060,16 @@
979
1060
  } else {
980
1061
  duration.milliseconds = input;
981
1062
  }
1063
+ } else if (matched) {
1064
+ sign = (matched[1] === "-") ? -1 : 1;
1065
+ duration = {
1066
+ y: 0,
1067
+ d: ~~matched[2] * sign,
1068
+ h: ~~matched[3] * sign,
1069
+ m: ~~matched[4] * sign,
1070
+ s: ~~matched[5] * sign,
1071
+ ms: ~~matched[6] * sign
1072
+ };
982
1073
  }
983
1074
 
984
1075
  ret = new Duration(duration);
@@ -996,12 +1087,14 @@
996
1087
  // default format
997
1088
  moment.defaultFormat = isoFormat;
998
1089
 
1090
+ // This function will be called whenever a moment is mutated.
1091
+ // It is intended to keep the offset in sync with the timezone.
1092
+ moment.updateOffset = function () {};
1093
+
999
1094
  // This function will load languages and then set the global language. If
1000
1095
  // no arguments are passed in, it will simply return the current global
1001
1096
  // language key.
1002
1097
  moment.lang = function (key, values) {
1003
- var i;
1004
-
1005
1098
  if (!key) {
1006
1099
  return moment.fn._lang._abbr;
1007
1100
  }
@@ -1044,11 +1137,11 @@
1044
1137
  },
1045
1138
 
1046
1139
  valueOf : function () {
1047
- return +this._d;
1140
+ return +this._d + ((this._offset || 0) * 60000);
1048
1141
  },
1049
1142
 
1050
1143
  unix : function () {
1051
- return Math.floor(+this._d / 1000);
1144
+ return Math.floor(+this / 1000);
1052
1145
  },
1053
1146
 
1054
1147
  toString : function () {
@@ -1056,11 +1149,11 @@
1056
1149
  },
1057
1150
 
1058
1151
  toDate : function () {
1059
- return this._d;
1152
+ return this._offset ? new Date(+this) : this._d;
1060
1153
  },
1061
1154
 
1062
- toJSON : function () {
1063
- return moment.utc(this).format('YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1155
+ toISOString : function () {
1156
+ return formatMoment(moment(this).utc(), 'YYYY-MM-DD[T]HH:mm:ss.SSS[Z]');
1064
1157
  },
1065
1158
 
1066
1159
  toArray : function () {
@@ -1088,11 +1181,11 @@
1088
1181
  },
1089
1182
 
1090
1183
  utc : function () {
1091
- this._isUTC = true;
1092
- return this;
1184
+ return this.zone(0);
1093
1185
  },
1094
1186
 
1095
1187
  local : function () {
1188
+ this.zone(0);
1096
1189
  this._isUTC = false;
1097
1190
  return this;
1098
1191
  },
@@ -1127,29 +1220,34 @@
1127
1220
  },
1128
1221
 
1129
1222
  diff : function (input, units, asFloat) {
1130
- var that = this._isUTC ? moment(input).utc() : moment(input).local(),
1223
+ var that = this._isUTC ? moment(input).zone(this._offset || 0) : moment(input).local(),
1131
1224
  zoneDiff = (this.zone() - that.zone()) * 6e4,
1132
1225
  diff, output;
1133
1226
 
1134
- if (units) {
1135
- // standardize on singular form
1136
- units = units.replace(/s$/, '');
1137
- }
1227
+ units = normalizeUnits(units);
1138
1228
 
1139
1229
  if (units === 'year' || units === 'month') {
1230
+ // average number of days in the months in the given dates
1140
1231
  diff = (this.daysInMonth() + that.daysInMonth()) * 432e5; // 24 * 60 * 60 * 1000 / 2
1232
+ // difference in months
1141
1233
  output = ((this.year() - that.year()) * 12) + (this.month() - that.month());
1142
- output += ((this - moment(this).startOf('month')) - (that - moment(that).startOf('month'))) / diff;
1234
+ // adjust by taking difference in days, average number of days
1235
+ // and dst in the given months.
1236
+ output += ((this - moment(this).startOf('month')) -
1237
+ (that - moment(that).startOf('month'))) / diff;
1238
+ // same as above but with zones, to negate all dst
1239
+ output -= ((this.zone() - moment(this).startOf('month').zone()) -
1240
+ (that.zone() - moment(that).startOf('month').zone())) * 6e4 / diff;
1143
1241
  if (units === 'year') {
1144
1242
  output = output / 12;
1145
1243
  }
1146
1244
  } else {
1147
- diff = (this - that) - zoneDiff;
1245
+ diff = (this - that);
1148
1246
  output = units === 'second' ? diff / 1e3 : // 1000
1149
1247
  units === 'minute' ? diff / 6e4 : // 1000 * 60
1150
1248
  units === 'hour' ? diff / 36e5 : // 1000 * 60 * 60
1151
- units === 'day' ? diff / 864e5 : // 1000 * 60 * 60 * 24
1152
- units === 'week' ? diff / 6048e5 : // 1000 * 60 * 60 * 24 * 7
1249
+ units === 'day' ? (diff - zoneDiff) / 864e5 : // 1000 * 60 * 60 * 24, negate dst
1250
+ units === 'week' ? (diff - zoneDiff) / 6048e5 : // 1000 * 60 * 60 * 24 * 7, negate dst
1153
1251
  diff;
1154
1252
  }
1155
1253
  return asFloat ? output : absRound(output);
@@ -1180,18 +1278,52 @@
1180
1278
  },
1181
1279
 
1182
1280
  isDST : function () {
1183
- return (this.zone() < moment([this.year()]).zone() ||
1184
- this.zone() < moment([this.year(), 5]).zone());
1281
+ return (this.zone() < this.clone().month(0).zone() ||
1282
+ this.zone() < this.clone().month(5).zone());
1185
1283
  },
1186
1284
 
1187
1285
  day : function (input) {
1188
1286
  var day = this._isUTC ? this._d.getUTCDay() : this._d.getDay();
1189
- return input == null ? day :
1190
- this.add({ d : input - day });
1287
+ if (input != null) {
1288
+ if (typeof input === 'string') {
1289
+ input = this.lang().weekdaysParse(input);
1290
+ if (typeof input !== 'number') {
1291
+ return this;
1292
+ }
1293
+ }
1294
+ return this.add({ d : input - day });
1295
+ } else {
1296
+ return day;
1297
+ }
1298
+ },
1299
+
1300
+ month : function (input) {
1301
+ var utc = this._isUTC ? 'UTC' : '',
1302
+ dayOfMonth,
1303
+ daysInMonth;
1304
+
1305
+ if (input != null) {
1306
+ if (typeof input === 'string') {
1307
+ input = this.lang().monthsParse(input);
1308
+ if (typeof input !== 'number') {
1309
+ return this;
1310
+ }
1311
+ }
1312
+
1313
+ dayOfMonth = this.date();
1314
+ this.date(1);
1315
+ this._d['set' + utc + 'Month'](input);
1316
+ this.date(Math.min(dayOfMonth, this.daysInMonth()));
1317
+
1318
+ moment.updateOffset(this);
1319
+ return this;
1320
+ } else {
1321
+ return this._d['get' + utc + 'Month']();
1322
+ }
1191
1323
  },
1192
1324
 
1193
1325
  startOf: function (units) {
1194
- units = units.replace(/s$/, '');
1326
+ units = normalizeUnits(units);
1195
1327
  // the following switch intentionally omits break keywords
1196
1328
  // to utilize falling through the cases.
1197
1329
  switch (units) {
@@ -1218,14 +1350,14 @@
1218
1350
 
1219
1351
  // weeks are a special case
1220
1352
  if (units === 'week') {
1221
- this.day(0);
1353
+ this.weekday(0);
1222
1354
  }
1223
1355
 
1224
1356
  return this;
1225
1357
  },
1226
1358
 
1227
1359
  endOf: function (units) {
1228
- return this.startOf(units).add(units.replace(/s?$/, 's'), 1).subtract('ms', 1);
1360
+ return this.startOf(units).add(units, 1).subtract('ms', 1);
1229
1361
  },
1230
1362
 
1231
1363
  isAfter: function (input, units) {
@@ -1243,8 +1375,42 @@
1243
1375
  return +this.clone().startOf(units) === +moment(input).startOf(units);
1244
1376
  },
1245
1377
 
1246
- zone : function () {
1247
- return this._isUTC ? 0 : this._d.getTimezoneOffset();
1378
+ min: function (other) {
1379
+ other = moment.apply(null, arguments);
1380
+ return other < this ? this : other;
1381
+ },
1382
+
1383
+ max: function (other) {
1384
+ other = moment.apply(null, arguments);
1385
+ return other > this ? this : other;
1386
+ },
1387
+
1388
+ zone : function (input) {
1389
+ var offset = this._offset || 0;
1390
+ if (input != null) {
1391
+ if (typeof input === "string") {
1392
+ input = timezoneMinutesFromString(input);
1393
+ }
1394
+ if (Math.abs(input) < 16) {
1395
+ input = input * 60;
1396
+ }
1397
+ this._offset = input;
1398
+ this._isUTC = true;
1399
+ if (offset !== input) {
1400
+ addOrSubtractDurationFromMoment(this, moment.duration(offset - input, 'm'), 1, true);
1401
+ }
1402
+ } else {
1403
+ return this._isUTC ? offset : this._d.getTimezoneOffset();
1404
+ }
1405
+ return this;
1406
+ },
1407
+
1408
+ zoneAbbr : function () {
1409
+ return this._isUTC ? "UTC" : "";
1410
+ },
1411
+
1412
+ zoneName : function () {
1413
+ return this._isUTC ? "Coordinated Universal Time" : "";
1248
1414
  },
1249
1415
 
1250
1416
  daysInMonth : function () {
@@ -1256,9 +1422,14 @@
1256
1422
  return input == null ? dayOfYear : this.add("d", (input - dayOfYear));
1257
1423
  },
1258
1424
 
1259
- isoWeek : function (input) {
1260
- var week = weekOfYear(this, 1, 4);
1261
- return input == null ? week : this.add("d", (input - week) * 7);
1425
+ weekYear : function (input) {
1426
+ var year = weekOfYear(this, this.lang()._week.dow, this.lang()._week.doy).year;
1427
+ return input == null ? year : this.add("y", (input - year));
1428
+ },
1429
+
1430
+ isoWeekYear : function (input) {
1431
+ var year = weekOfYear(this, 1, 4).year;
1432
+ return input == null ? year : this.add("y", (input - year));
1262
1433
  },
1263
1434
 
1264
1435
  week : function (input) {
@@ -1266,6 +1437,23 @@
1266
1437
  return input == null ? week : this.add("d", (input - week) * 7);
1267
1438
  },
1268
1439
 
1440
+ isoWeek : function (input) {
1441
+ var week = weekOfYear(this, 1, 4).week;
1442
+ return input == null ? week : this.add("d", (input - week) * 7);
1443
+ },
1444
+
1445
+ weekday : function (input) {
1446
+ var weekday = (this._d.getDay() + 7 - this.lang()._week.dow) % 7;
1447
+ return input == null ? weekday : this.add("d", input - weekday);
1448
+ },
1449
+
1450
+ isoWeekday : function (input) {
1451
+ // behaves the same as moment#day except
1452
+ // as a getter, returns 7 instead of 0 (1-7 range instead of 0-6)
1453
+ // as a setter, sunday should belong to the previous week.
1454
+ return input == null ? this.day() || 7 : this.day(this.day() % 7 ? input : input - 7);
1455
+ },
1456
+
1269
1457
  // If passed a language key, it will set the language for this
1270
1458
  // instance. Otherwise, it will return the language configuration
1271
1459
  // variables for this instance.
@@ -1285,6 +1473,7 @@
1285
1473
  var utc = this._isUTC ? 'UTC' : '';
1286
1474
  if (input != null) {
1287
1475
  this._d['set' + utc + key](input);
1476
+ moment.updateOffset(this);
1288
1477
  return this;
1289
1478
  } else {
1290
1479
  return this._d['get' + utc + key]();
@@ -1302,15 +1491,49 @@
1302
1491
 
1303
1492
  // add plural methods
1304
1493
  moment.fn.days = moment.fn.day;
1494
+ moment.fn.months = moment.fn.month;
1305
1495
  moment.fn.weeks = moment.fn.week;
1306
1496
  moment.fn.isoWeeks = moment.fn.isoWeek;
1307
1497
 
1498
+ // add aliased format methods
1499
+ moment.fn.toJSON = moment.fn.toISOString;
1500
+
1308
1501
  /************************************
1309
1502
  Duration Prototype
1310
1503
  ************************************/
1311
1504
 
1312
1505
 
1313
1506
  moment.duration.fn = Duration.prototype = {
1507
+ _bubble : function () {
1508
+ var milliseconds = this._milliseconds,
1509
+ days = this._days,
1510
+ months = this._months,
1511
+ data = this._data,
1512
+ seconds, minutes, hours, years;
1513
+
1514
+ // The following code bubbles up values, see the tests for
1515
+ // examples of what that means.
1516
+ data.milliseconds = milliseconds % 1000;
1517
+
1518
+ seconds = absRound(milliseconds / 1000);
1519
+ data.seconds = seconds % 60;
1520
+
1521
+ minutes = absRound(seconds / 60);
1522
+ data.minutes = minutes % 60;
1523
+
1524
+ hours = absRound(minutes / 60);
1525
+ data.hours = hours % 24;
1526
+
1527
+ days += absRound(hours / 24);
1528
+ data.days = days % 30;
1529
+
1530
+ months += absRound(days / 30);
1531
+ data.months = months % 12;
1532
+
1533
+ years = absRound(months / 12);
1534
+ data.years = years;
1535
+ },
1536
+
1314
1537
  weeks : function () {
1315
1538
  return absRound(this.days() / 7);
1316
1539
  },
@@ -1318,7 +1541,8 @@
1318
1541
  valueOf : function () {
1319
1542
  return this._milliseconds +
1320
1543
  this._days * 864e5 +
1321
- this._months * 2592e6;
1544
+ (this._months % 12) * 2592e6 +
1545
+ ~~(this._months / 12) * 31536e6;
1322
1546
  },
1323
1547
 
1324
1548
  humanize : function (withSuffix) {
@@ -1332,6 +1556,41 @@
1332
1556
  return this.lang().postformat(output);
1333
1557
  },
1334
1558
 
1559
+ add : function (input, val) {
1560
+ // supports only 2.0-style add(1, 's') or add(moment)
1561
+ var dur = moment.duration(input, val);
1562
+
1563
+ this._milliseconds += dur._milliseconds;
1564
+ this._days += dur._days;
1565
+ this._months += dur._months;
1566
+
1567
+ this._bubble();
1568
+
1569
+ return this;
1570
+ },
1571
+
1572
+ subtract : function (input, val) {
1573
+ var dur = moment.duration(input, val);
1574
+
1575
+ this._milliseconds -= dur._milliseconds;
1576
+ this._days -= dur._days;
1577
+ this._months -= dur._months;
1578
+
1579
+ this._bubble();
1580
+
1581
+ return this;
1582
+ },
1583
+
1584
+ get : function (units) {
1585
+ units = normalizeUnits(units);
1586
+ return this[units.toLowerCase() + 's']();
1587
+ },
1588
+
1589
+ as : function (units) {
1590
+ units = normalizeUnits(units);
1591
+ return this['as' + units.charAt(0).toUpperCase() + units.slice(1) + 's']();
1592
+ },
1593
+
1335
1594
  lang : moment.fn.lang
1336
1595
  };
1337
1596
 
@@ -1355,6 +1614,9 @@
1355
1614
  }
1356
1615
 
1357
1616
  makeDurationAsGetter('Weeks', 6048e5);
1617
+ moment.duration.fn.asMonths = function () {
1618
+ return (+this - this.years() * 31536e6) / 2592e6 + this.years() * 12;
1619
+ };
1358
1620
 
1359
1621
 
1360
1622
  /************************************