momentjs-rails 2.0.0.2 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
  /************************************