sugar-rails 1.3.7 → 1.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (42) hide show
  1. checksums.yaml +7 -0
  2. data/.ruby-gemset +1 -0
  3. data/.ruby-version +1 -0
  4. data/README.md +3 -50
  5. data/{vendor → app}/assets/javascripts/sugar-development.js +1914 -1225
  6. data/app/assets/javascripts/sugar-full.js +200 -0
  7. data/app/assets/javascripts/sugar.js +132 -0
  8. data/copy_release.sh +4 -7
  9. data/lib/sugar/rails/version.rb +2 -2
  10. metadata +16 -58
  11. data/.rvmrc +0 -1
  12. data/lib/generators/sugar/build/build_generator.rb +0 -107
  13. data/lib/generators/sugar/install/install_generator.rb +0 -35
  14. data/vendor/assets/javascripts/precompiled/development/array.js +0 -1203
  15. data/vendor/assets/javascripts/precompiled/development/core.js +0 -365
  16. data/vendor/assets/javascripts/precompiled/development/date.js +0 -2267
  17. data/vendor/assets/javascripts/precompiled/development/date_locales.js +0 -1179
  18. data/vendor/assets/javascripts/precompiled/development/date_ranges.js +0 -208
  19. data/vendor/assets/javascripts/precompiled/development/es5.js +0 -474
  20. data/vendor/assets/javascripts/precompiled/development/function.js +0 -224
  21. data/vendor/assets/javascripts/precompiled/development/inflections.js +0 -410
  22. data/vendor/assets/javascripts/precompiled/development/language.js +0 -383
  23. data/vendor/assets/javascripts/precompiled/development/number.js +0 -428
  24. data/vendor/assets/javascripts/precompiled/development/object.js +0 -419
  25. data/vendor/assets/javascripts/precompiled/development/regexp.js +0 -92
  26. data/vendor/assets/javascripts/precompiled/development/string.js +0 -894
  27. data/vendor/assets/javascripts/precompiled/minified/array.js +0 -18
  28. data/vendor/assets/javascripts/precompiled/minified/core.js +0 -9
  29. data/vendor/assets/javascripts/precompiled/minified/date.js +0 -44
  30. data/vendor/assets/javascripts/precompiled/minified/date_locales.js +0 -49
  31. data/vendor/assets/javascripts/precompiled/minified/date_ranges.js +0 -4
  32. data/vendor/assets/javascripts/precompiled/minified/es5.js +0 -8
  33. data/vendor/assets/javascripts/precompiled/minified/function.js +0 -4
  34. data/vendor/assets/javascripts/precompiled/minified/inflections.js +0 -11
  35. data/vendor/assets/javascripts/precompiled/minified/language.js +0 -19
  36. data/vendor/assets/javascripts/precompiled/minified/number.js +0 -5
  37. data/vendor/assets/javascripts/precompiled/minified/object.js +0 -6
  38. data/vendor/assets/javascripts/precompiled/minified/regexp.js +0 -2
  39. data/vendor/assets/javascripts/precompiled/minified/string.js +0 -12
  40. data/vendor/assets/javascripts/precompiled/readme.txt +0 -3
  41. data/vendor/assets/javascripts/sugar-full.js +0 -199
  42. data/vendor/assets/javascripts/sugar.js +0 -120
@@ -1,365 +0,0 @@
1
-
2
-
3
- /***
4
- * @package Core
5
- * @description Internal utility and common methods.
6
- ***/
7
-
8
-
9
- // A few optimizations for Google Closure Compiler will save us a couple kb in the release script.
10
- var object = Object, array = Array, regexp = RegExp, date = Date, string = String, number = Number, math = Math, Undefined;
11
-
12
- // The global context
13
- var globalContext = typeof global !== 'undefined' ? global : this;
14
-
15
- // defineProperty exists in IE8 but will error when trying to define a property on
16
- // native objects. IE8 does not have defineProperies, however, so this check saves a try/catch block.
17
- var definePropertySupport = object.defineProperty && object.defineProperties;
18
-
19
- // Class initializers and class helpers
20
-
21
- var ClassNames = 'Array,Boolean,Date,Function,Number,String,RegExp'.split(',');
22
-
23
- var isArray = buildClassCheck(ClassNames[0]);
24
- var isBoolean = buildClassCheck(ClassNames[1]);
25
- var isDate = buildClassCheck(ClassNames[2]);
26
- var isFunction = buildClassCheck(ClassNames[3]);
27
- var isNumber = buildClassCheck(ClassNames[4]);
28
- var isString = buildClassCheck(ClassNames[5]);
29
- var isRegExp = buildClassCheck(ClassNames[6]);
30
-
31
- function buildClassCheck(type) {
32
- return function(obj) {
33
- return className(obj) === '[object '+type+']';
34
- }
35
- }
36
-
37
- function className(obj) {
38
- return object.prototype.toString.call(obj);
39
- }
40
-
41
- function initializeClasses() {
42
- initializeClass(object);
43
- iterateOverObject(ClassNames, function(i,name) {
44
- initializeClass(globalContext[name]);
45
- });
46
- }
47
-
48
- function initializeClass(klass) {
49
- if(klass['SugarMethods']) return;
50
- defineProperty(klass, 'SugarMethods', {});
51
- extend(klass, false, false, {
52
- 'restore': function() {
53
- var all = arguments.length === 0, methods = multiArgs(arguments);
54
- iterateOverObject(klass['SugarMethods'], function(name, m) {
55
- if(all || methods.indexOf(name) > -1) {
56
- defineProperty(m.instance ? klass.prototype : klass, name, m.method);
57
- }
58
- });
59
- },
60
- 'extend': function(methods, override, instance) {
61
- extend(klass, instance !== false, override, methods);
62
- }
63
- });
64
- }
65
-
66
- // Class extending methods
67
-
68
- function extend(klass, instance, override, methods) {
69
- var extendee = instance ? klass.prototype : klass, original;
70
- initializeClass(klass);
71
- iterateOverObject(methods, function(name, method) {
72
- original = extendee[name];
73
- if(typeof override === 'function') {
74
- method = wrapNative(extendee[name], method, override);
75
- }
76
- if(override !== false || !extendee[name]) {
77
- defineProperty(extendee, name, method);
78
- }
79
- // If the method is internal to Sugar, then store a reference so it can be restored later.
80
- klass['SugarMethods'][name] = { instance: instance, method: method, original: original };
81
- });
82
- }
83
-
84
- function extendSimilar(klass, instance, override, set, fn) {
85
- var methods = {};
86
- set = isString(set) ? set.split(',') : set;
87
- set.forEach(function(name, i) {
88
- fn(methods, name, i);
89
- });
90
- extend(klass, instance, override, methods);
91
- }
92
-
93
- function wrapNative(nativeFn, extendedFn, condition) {
94
- return function() {
95
- if(nativeFn && (condition === true || !condition.apply(this, arguments))) {
96
- return nativeFn.apply(this, arguments);
97
- } else {
98
- return extendedFn.apply(this, arguments);
99
- }
100
- }
101
- }
102
-
103
- function defineProperty(target, name, method) {
104
- if(definePropertySupport) {
105
- object.defineProperty(target, name, { 'value': method, 'configurable': true, 'enumerable': false, 'writable': true });
106
- } else {
107
- target[name] = method;
108
- }
109
- }
110
-
111
-
112
- // Argument helpers
113
-
114
- function multiArgs(args, fn) {
115
- var result = [], i;
116
- for(i = 0; i < args.length; i++) {
117
- result.push(args[i]);
118
- if(fn) fn.call(args, args[i], i);
119
- }
120
- return result;
121
- }
122
-
123
- function flattenedArgs(obj, fn, from) {
124
- multiArgs(array.prototype.concat.apply([], array.prototype.slice.call(obj, from || 0)), fn);
125
- }
126
-
127
- function checkCallback(fn) {
128
- if(!fn || !fn.call) {
129
- throw new TypeError('Callback is not callable');
130
- }
131
- }
132
-
133
-
134
- // General helpers
135
-
136
- function isDefined(o) {
137
- return o !== Undefined;
138
- }
139
-
140
- function isUndefined(o) {
141
- return o === Undefined;
142
- }
143
-
144
-
145
- // Object helpers
146
-
147
- function isObjectPrimitive(obj) {
148
- // Check for null
149
- return obj && typeof obj === 'object';
150
- }
151
-
152
- function isObject(obj) {
153
- // === on the constructor is not safe across iframes
154
- // 'hasOwnProperty' ensures that the object also inherits
155
- // from Object, which is false for DOMElements in IE.
156
- return !!obj && className(obj) === '[object Object]' && 'hasOwnProperty' in obj;
157
- }
158
-
159
- function hasOwnProperty(obj, key) {
160
- return object['hasOwnProperty'].call(obj, key);
161
- }
162
-
163
- function iterateOverObject(obj, fn) {
164
- var key;
165
- for(key in obj) {
166
- if(!hasOwnProperty(obj, key)) continue;
167
- if(fn.call(obj, key, obj[key], obj) === false) break;
168
- }
169
- }
170
-
171
- function simpleMerge(target, source) {
172
- iterateOverObject(source, function(key) {
173
- target[key] = source[key];
174
- });
175
- return target;
176
- }
177
-
178
- // Hash definition
179
-
180
- function Hash(obj) {
181
- simpleMerge(this, obj);
182
- };
183
-
184
- Hash.prototype.constructor = object;
185
-
186
- // Number helpers
187
-
188
- function getRange(start, stop, fn, step) {
189
- var arr = [], i = parseInt(start), down = step < 0;
190
- while((!down && i <= stop) || (down && i >= stop)) {
191
- arr.push(i);
192
- if(fn) fn.call(this, i);
193
- i += step || 1;
194
- }
195
- return arr;
196
- }
197
-
198
- function round(val, precision, method) {
199
- var fn = math[method || 'round'];
200
- var multiplier = math.pow(10, math.abs(precision || 0));
201
- if(precision < 0) multiplier = 1 / multiplier;
202
- return fn(val * multiplier) / multiplier;
203
- }
204
-
205
- function ceil(val, precision) {
206
- return round(val, precision, 'ceil');
207
- }
208
-
209
- function floor(val, precision) {
210
- return round(val, precision, 'floor');
211
- }
212
-
213
- function padNumber(num, place, sign, base) {
214
- var str = math.abs(num).toString(base || 10);
215
- str = repeatString(place - str.replace(/\.\d+/, '').length, '0') + str;
216
- if(sign || num < 0) {
217
- str = (num < 0 ? '-' : '+') + str;
218
- }
219
- return str;
220
- }
221
-
222
- function getOrdinalizedSuffix(num) {
223
- if(num >= 11 && num <= 13) {
224
- return 'th';
225
- } else {
226
- switch(num % 10) {
227
- case 1: return 'st';
228
- case 2: return 'nd';
229
- case 3: return 'rd';
230
- default: return 'th';
231
- }
232
- }
233
- }
234
-
235
-
236
- // String helpers
237
-
238
- // WhiteSpace/LineTerminator as defined in ES5.1 plus Unicode characters in the Space, Separator category.
239
- function getTrimmableCharacters() {
240
- return '\u0009\u000A\u000B\u000C\u000D\u0020\u00A0\u1680\u180E\u2000\u2001\u2002\u2003\u2004\u2005\u2006\u2007\u2008\u2009\u200A\u202F\u205F\u2028\u2029\u3000\uFEFF';
241
- }
242
-
243
- function repeatString(times, str) {
244
- return array(math.max(0, isDefined(times) ? times : 1) + 1).join(str || '');
245
- }
246
-
247
-
248
- // RegExp helpers
249
-
250
- function getRegExpFlags(reg, add) {
251
- var flags = reg.toString().match(/[^/]*$/)[0];
252
- if(add) {
253
- flags = (flags + add).split('').sort().join('').replace(/([gimy])\1+/g, '$1');
254
- }
255
- return flags;
256
- }
257
-
258
- function escapeRegExp(str) {
259
- if(!isString(str)) str = string(str);
260
- return str.replace(/([\\/'*+?|()\[\]{}.^$])/g,'\\$1');
261
- }
262
-
263
-
264
- // Specialized helpers
265
-
266
-
267
- // Used by Array#unique and Object.equal
268
-
269
- function stringify(thing, stack) {
270
- var type = typeof thing,
271
- thingIsObject,
272
- thingIsArray,
273
- klass, value,
274
- arr, key, i;
275
-
276
- // Return quickly if string to save cycles
277
- if(type === 'string') return thing;
278
-
279
- klass = object.prototype.toString.call(thing)
280
- thingIsObject = isObject(thing);
281
- thingIsArray = klass === '[object Array]';
282
-
283
- if(thing != null && thingIsObject || thingIsArray) {
284
- // This method for checking for cyclic structures was egregiously stolen from
285
- // the ingenious method by @kitcambridge from the Underscore script:
286
- // https://github.com/documentcloud/underscore/issues/240
287
- if(!stack) stack = [];
288
- // Allowing a step into the structure before triggering this
289
- // script to save cycles on standard JSON structures and also to
290
- // try as hard as possible to catch basic properties that may have
291
- // been modified.
292
- if(stack.length > 1) {
293
- i = stack.length;
294
- while (i--) {
295
- if (stack[i] === thing) {
296
- return 'CYC';
297
- }
298
- }
299
- }
300
- stack.push(thing);
301
- value = string(thing.constructor);
302
- arr = thingIsArray ? thing : object.keys(thing).sort();
303
- for(i = 0; i < arr.length; i++) {
304
- key = thingIsArray ? i : arr[i];
305
- value += key + stringify(thing[key], stack);
306
- }
307
- stack.pop();
308
- } else if(1 / thing === -Infinity) {
309
- value = '-0';
310
- } else {
311
- value = string(thing && thing.valueOf ? thing.valueOf() : thing);
312
- }
313
- return type + klass + value;
314
- }
315
-
316
- function isEqual(a, b) {
317
- if(objectIsMatchedByValue(a) && objectIsMatchedByValue(b)) {
318
- return stringify(a) === stringify(b);
319
- } else {
320
- return a === b;
321
- }
322
- }
323
-
324
- function objectIsMatchedByValue(obj) {
325
- var klass = className(obj);
326
- return klass === '[object Date]' ||
327
- klass === '[object Array]' ||
328
- klass === '[object String]' ||
329
- klass === '[object Number]' ||
330
- klass === '[object RegExp]' ||
331
- klass === '[object Boolean]' ||
332
- klass === '[object Arguments]' ||
333
- isObject(obj);
334
- }
335
-
336
-
337
- // Used by Array#at and String#at
338
-
339
- function entryAtIndex(arr, args, str) {
340
- var result = [], length = arr.length, loop = args[args.length - 1] !== false, r;
341
- multiArgs(args, function(index) {
342
- if(isBoolean(index)) return false;
343
- if(loop) {
344
- index = index % length;
345
- if(index < 0) index = length + index;
346
- }
347
- r = str ? arr.charAt(index) || '' : arr[index];
348
- result.push(r);
349
- });
350
- return result.length < 2 ? result[0] : result;
351
- }
352
-
353
-
354
- // Object class methods implemented as instance methods
355
-
356
- function buildObjectInstanceMethods(set, target) {
357
- extendSimilar(target, true, false, set, function(methods, name) {
358
- methods[name + (name === 'equal' ? 's' : '')] = function() {
359
- return object[name].apply(null, [this].concat(multiArgs(arguments)));
360
- }
361
- });
362
- }
363
-
364
- initializeClasses();
365
-
@@ -1,2267 +0,0 @@
1
-
2
- /***
3
- * @package Date
4
- * @dependency core
5
- * @description Date parsing and formatting, relative formats like "1 minute ago", Number methods like "daysAgo", localization support with default English locale definition.
6
- *
7
- ***/
8
-
9
- var English;
10
- var CurrentLocalization;
11
-
12
- var TimeFormat = ['ampm','hour','minute','second','ampm','utc','offset_sign','offset_hours','offset_minutes','ampm']
13
- var DecimalReg = '(?:[,.]\\d+)?';
14
- var HoursReg = '\\d{1,2}' + DecimalReg;
15
- var SixtyReg = '[0-5]\\d' + DecimalReg;
16
- var RequiredTime = '({t})?\\s*('+HoursReg+')(?:{h}('+SixtyReg+')?{m}(?::?('+SixtyReg+'){s})?\\s*(?:({t})|(Z)|(?:([+-])(\\d{2,2})(?::?(\\d{2,2}))?)?)?|\\s*({t}))';
17
-
18
- var KanjiDigits = '〇一二三四五六七八九十百千万';
19
- var FullWidthDigits = '0123456789';
20
- var AsianDigitMap = {};
21
- var AsianDigitReg;
22
-
23
- var DateArgumentUnits;
24
- var DateUnitsReversed;
25
- var CoreDateFormats = [];
26
-
27
- var DateOutputFormats = [
28
- {
29
- token: 'f{1,4}|ms|milliseconds',
30
- format: function(d) {
31
- return callDateGet(d, 'Milliseconds');
32
- }
33
- },
34
- {
35
- token: 'ss?|seconds',
36
- format: function(d, len) {
37
- return callDateGet(d, 'Seconds');
38
- }
39
- },
40
- {
41
- token: 'mm?|minutes',
42
- format: function(d, len) {
43
- return callDateGet(d, 'Minutes');
44
- }
45
- },
46
- {
47
- token: 'hh?|hours|12hr',
48
- format: function(d) {
49
- return getShortHour(d);
50
- }
51
- },
52
- {
53
- token: 'HH?|24hr',
54
- format: function(d) {
55
- return callDateGet(d, 'Hours');
56
- }
57
- },
58
- {
59
- token: 'dd?|date|day',
60
- format: function(d) {
61
- return callDateGet(d, 'Date');
62
- }
63
- },
64
- {
65
- token: 'dow|weekday',
66
- word: true,
67
- format: function(d, loc, n, t) {
68
- var dow = callDateGet(d, 'Day');
69
- return loc['weekdays'][dow + (n - 1) * 7];
70
- }
71
- },
72
- {
73
- token: 'MM?',
74
- format: function(d) {
75
- return callDateGet(d, 'Month') + 1;
76
- }
77
- },
78
- {
79
- token: 'mon|month',
80
- word: true,
81
- format: function(d, loc, n, len) {
82
- var month = callDateGet(d, 'Month');
83
- return loc['months'][month + (n - 1) * 12];
84
- }
85
- },
86
- {
87
- token: 'y{2,4}|year',
88
- format: function(d) {
89
- return callDateGet(d, 'FullYear');
90
- }
91
- },
92
- {
93
- token: '[Tt]{1,2}',
94
- format: function(d, loc, n, format) {
95
- if(loc['ampm'].length == 0) return '';
96
- var hours = callDateGet(d, 'Hours');
97
- var str = loc['ampm'][floor(hours / 12)];
98
- if(format.length === 1) str = str.slice(0,1);
99
- if(format.slice(0,1) === 'T') str = str.toUpperCase();
100
- return str;
101
- }
102
- },
103
- {
104
- token: 'z{1,4}|tz|timezone',
105
- text: true,
106
- format: function(d, loc, n, format) {
107
- var tz = d.getUTCOffset();
108
- if(format == 'z' || format == 'zz') {
109
- tz = tz.replace(/(\d{2})(\d{2})/, function(f,h,m) {
110
- return padNumber(h, format.length);
111
- });
112
- }
113
- return tz;
114
- }
115
- },
116
- {
117
- token: 'iso(tz|timezone)',
118
- format: function(d) {
119
- return d.getUTCOffset(true);
120
- }
121
- },
122
- {
123
- token: 'ord',
124
- format: function(d) {
125
- var date = callDateGet(d, 'Date');
126
- return date + getOrdinalizedSuffix(date);
127
- }
128
- }
129
- ];
130
-
131
- var DateUnits = [
132
- {
133
- unit: 'year',
134
- method: 'FullYear',
135
- ambiguous: true,
136
- multiplier: function(d) {
137
- var adjust = d ? (d.isLeapYear() ? 1 : 0) : 0.25;
138
- return (365 + adjust) * 24 * 60 * 60 * 1000;
139
- }
140
- },
141
- {
142
- unit: 'month',
143
- method: 'Month',
144
- ambiguous: true,
145
- multiplier: function(d, ms) {
146
- var days = 30.4375, inMonth;
147
- if(d) {
148
- inMonth = d.daysInMonth();
149
- if(ms <= inMonth.days()) {
150
- days = inMonth;
151
- }
152
- }
153
- return days * 24 * 60 * 60 * 1000;
154
- },
155
- error: 0.919
156
- },
157
- {
158
- unit: 'week',
159
- method: 'Week',
160
- multiplier: function() {
161
- return 7 * 24 * 60 * 60 * 1000;
162
- }
163
- },
164
- {
165
- unit: 'day',
166
- method: 'Date',
167
- ambiguous: true,
168
- multiplier: function() {
169
- return 24 * 60 * 60 * 1000;
170
- }
171
- },
172
- {
173
- unit: 'hour',
174
- method: 'Hours',
175
- multiplier: function() {
176
- return 60 * 60 * 1000;
177
- }
178
- },
179
- {
180
- unit: 'minute',
181
- method: 'Minutes',
182
- multiplier: function() {
183
- return 60 * 1000;
184
- }
185
- },
186
- {
187
- unit: 'second',
188
- method: 'Seconds',
189
- multiplier: function() {
190
- return 1000;
191
- }
192
- },
193
- {
194
- unit: 'millisecond',
195
- method: 'Milliseconds',
196
- multiplier: function() {
197
- return 1;
198
- }
199
- }
200
- ];
201
-
202
-
203
-
204
-
205
- // Date Localization
206
-
207
- var Localizations = {};
208
-
209
- // Localization object
210
-
211
- function Localization(l) {
212
- simpleMerge(this, l);
213
- this.compiledFormats = CoreDateFormats.concat();
214
- }
215
-
216
- Localization.prototype = {
217
-
218
- getMonth: function(n) {
219
- if(isNumber(n)) {
220
- return n - 1;
221
- } else {
222
- return this['months'].indexOf(n) % 12;
223
- }
224
- },
225
-
226
- getWeekday: function(n) {
227
- return this['weekdays'].indexOf(n) % 7;
228
- },
229
-
230
- getNumber: function(n) {
231
- var i;
232
- if(isNumber(n)) {
233
- return n;
234
- } else if(n && (i = this['numbers'].indexOf(n)) !== -1) {
235
- return (i + 1) % 10;
236
- } else {
237
- return 1;
238
- }
239
- },
240
-
241
- getNumericDate: function(n) {
242
- var self = this;
243
- return n.replace(regexp(this['num'], 'g'), function(d) {
244
- var num = self.getNumber(d);
245
- return num || '';
246
- });
247
- },
248
-
249
- getEnglishUnit: function(n) {
250
- return English['units'][this['units'].indexOf(n) % 8];
251
- },
252
-
253
- getRelativeFormat: function(adu) {
254
- return this.convertAdjustedToFormat(adu, adu[2] > 0 ? 'future' : 'past');
255
- },
256
-
257
- getDuration: function(ms) {
258
- return this.convertAdjustedToFormat(getAdjustedUnit(ms), 'duration');
259
- },
260
-
261
- hasVariant: function(code) {
262
- code = code || this.code;
263
- return code === 'en' || code === 'en-US' ? true : this['variant'];
264
- },
265
-
266
- matchAM: function(str) {
267
- return str === this['ampm'][0];
268
- },
269
-
270
- matchPM: function(str) {
271
- return str && str === this['ampm'][1];
272
- },
273
-
274
- convertAdjustedToFormat: function(adu, mode) {
275
- var sign, unit, mult,
276
- num = adu[0],
277
- u = adu[1],
278
- ms = adu[2],
279
- format = this[mode] || this['relative'];
280
- if(isFunction(format)) {
281
- return format.call(this, num, u, ms, mode);
282
- }
283
- mult = this['plural'] && num > 1 ? 1 : 0;
284
- unit = this['units'][mult * 8 + u] || this['units'][u];
285
- if(this['capitalizeUnit']) unit = simpleCapitalize(unit);
286
- sign = this['modifiers'].filter(function(m) { return m.name == 'sign' && m.value == (ms > 0 ? 1 : -1); })[0];
287
- return format.replace(/\{(.*?)\}/g, function(full, match) {
288
- switch(match) {
289
- case 'num': return num;
290
- case 'unit': return unit;
291
- case 'sign': return sign.src;
292
- }
293
- });
294
- },
295
-
296
- getFormats: function() {
297
- return this.cachedFormat ? [this.cachedFormat].concat(this.compiledFormats) : this.compiledFormats;
298
- },
299
-
300
- addFormat: function(src, allowsTime, match, variant, iso) {
301
- var to = match || [], loc = this, time, timeMarkers, lastIsNumeral;
302
-
303
- src = src.replace(/\s+/g, '[-,. ]*');
304
- src = src.replace(/\{([^,]+?)\}/g, function(all, k) {
305
- var value, arr, result,
306
- opt = k.match(/\?$/),
307
- nc = k.match(/^(\d+)\??$/),
308
- slice = k.match(/(\d)(?:-(\d))?/),
309
- key = k.replace(/[^a-z]+$/, '');
310
- if(nc) {
311
- value = loc['tokens'][nc[1]];
312
- } else if(loc[key]) {
313
- value = loc[key];
314
- } else if(loc[key + 's']) {
315
- value = loc[key + 's'];
316
- if(slice) {
317
- // Can't use filter here as Prototype hijacks the method and doesn't
318
- // pass an index, so use a simple loop instead!
319
- arr = [];
320
- value.forEach(function(m, i) {
321
- var mod = i % (loc['units'] ? 8 : value.length);
322
- if(mod >= slice[1] && mod <= (slice[2] || slice[1])) {
323
- arr.push(m);
324
- }
325
- });
326
- value = arr;
327
- }
328
- value = arrayToAlternates(value);
329
- }
330
- if(nc) {
331
- result = '(?:' + value + ')';
332
- } else {
333
- if(!match) {
334
- to.push(key);
335
- }
336
- result = '(' + value + ')';
337
- }
338
- if(opt) {
339
- result += '?';
340
- }
341
- return result;
342
- });
343
- if(allowsTime) {
344
- time = prepareTime(RequiredTime, loc, iso);
345
- timeMarkers = ['t','[\\s\\u3000]'].concat(loc['timeMarker']);
346
- lastIsNumeral = src.match(/\\d\{\d,\d\}\)+\??$/);
347
- addDateInputFormat(loc, '(?:' + time + ')[,\\s\\u3000]+?' + src, TimeFormat.concat(to), variant);
348
- addDateInputFormat(loc, src + '(?:[,\\s]*(?:' + timeMarkers.join('|') + (lastIsNumeral ? '+' : '*') +')' + time + ')?', to.concat(TimeFormat), variant);
349
- } else {
350
- addDateInputFormat(loc, src, to, variant);
351
- }
352
- }
353
-
354
- };
355
-
356
-
357
- // Localization helpers
358
-
359
- function getLocalization(localeCode, fallback) {
360
- var loc;
361
- if(!isString(localeCode)) localeCode = '';
362
- loc = Localizations[localeCode] || Localizations[localeCode.slice(0,2)];
363
- if(fallback === false && !loc) {
364
- throw new Error('Invalid locale.');
365
- }
366
- return loc || CurrentLocalization;
367
- }
368
-
369
- function setLocalization(localeCode, set) {
370
- var loc, canAbbreviate;
371
-
372
- function initializeField(name) {
373
- var val = loc[name];
374
- if(isString(val)) {
375
- loc[name] = val.split(',');
376
- } else if(!val) {
377
- loc[name] = [];
378
- }
379
- }
380
-
381
- function eachAlternate(str, fn) {
382
- str = str.split('+').map(function(split) {
383
- return split.replace(/(.+):(.+)$/, function(full, base, suffixes) {
384
- return suffixes.split('|').map(function(suffix) {
385
- return base + suffix;
386
- }).join('|');
387
- });
388
- }).join('|');
389
- return str.split('|').forEach(fn);
390
- }
391
-
392
- function setArray(name, abbreviate, multiple) {
393
- var arr = [];
394
- loc[name].forEach(function(full, i) {
395
- if(abbreviate) {
396
- full += '+' + full.slice(0,3);
397
- }
398
- eachAlternate(full, function(day, j) {
399
- arr[j * multiple + i] = day.toLowerCase();
400
- });
401
- });
402
- loc[name] = arr;
403
- }
404
-
405
- function getDigit(start, stop, allowNumbers) {
406
- var str = '\\d{' + start + ',' + stop + '}';
407
- if(allowNumbers) str += '|(?:' + arrayToAlternates(loc['numbers']) + ')+';
408
- return str;
409
- }
410
-
411
- function getNum() {
412
- var arr = ['\\d+'].concat(loc['articles']);
413
- if(loc['numbers']) arr = arr.concat(loc['numbers']);
414
- return arrayToAlternates(arr);
415
- }
416
-
417
- function setDefault(name, value) {
418
- loc[name] = loc[name] || value;
419
- }
420
-
421
- function setModifiers() {
422
- var arr = [];
423
- loc.modifiersByName = {};
424
- loc['modifiers'].forEach(function(modifier) {
425
- var name = modifier.name;
426
- eachAlternate(modifier.src, function(t) {
427
- var locEntry = loc[name];
428
- loc.modifiersByName[t] = modifier;
429
- arr.push({ name: name, src: t, value: modifier.value });
430
- loc[name] = locEntry ? locEntry + '|' + t : t;
431
- });
432
- });
433
- loc['day'] += '|' + arrayToAlternates(loc['weekdays']);
434
- loc['modifiers'] = arr;
435
- }
436
-
437
- // Initialize the locale
438
- loc = new Localization(set);
439
- initializeField('modifiers');
440
- 'months,weekdays,units,numbers,articles,tokens,timeMarker,ampm,timeSuffixes,dateParse,timeParse'.split(',').forEach(initializeField);
441
-
442
- canAbbreviate = !loc['monthSuffix'];
443
-
444
- setArray('months', canAbbreviate, 12);
445
- setArray('weekdays', canAbbreviate, 7);
446
- setArray('units', false, 8);
447
- setArray('numbers', false, 10);
448
-
449
- setDefault('code', localeCode);
450
- setDefault('date', getDigit(1,2, loc['digitDate']));
451
- setDefault('year', "'\\d{2}|" + getDigit(4,4));
452
- setDefault('num', getNum());
453
-
454
- setModifiers();
455
-
456
- if(loc['monthSuffix']) {
457
- loc['month'] = getDigit(1,2);
458
- loc['months'] = getRange(1, 12).map(function(n) { return n + loc['monthSuffix']; });
459
- }
460
- loc['full_month'] = getDigit(1,2) + '|' + arrayToAlternates(loc['months']);
461
-
462
- // The order of these formats is very important. Order is reversed so formats that come
463
- // later will take precedence over formats that come before. This generally means that
464
- // more specific formats should come later, however, the {year} format should come before
465
- // {day}, as 2011 needs to be parsed as a year (2011) and not date (20) + hours (11)
466
-
467
- // If the locale has time suffixes then add a time only format for that locale
468
- // that is separate from the core English-based one.
469
- if(loc['timeSuffixes'].length > 0) {
470
- loc.addFormat(prepareTime(RequiredTime, loc), false, TimeFormat)
471
- }
472
-
473
- loc.addFormat('{day}', true);
474
- loc.addFormat('{month}' + (loc['monthSuffix'] || ''));
475
- loc.addFormat('{year}' + (loc['yearSuffix'] || ''));
476
-
477
- loc['timeParse'].forEach(function(src) {
478
- loc.addFormat(src, true);
479
- });
480
-
481
- loc['dateParse'].forEach(function(src) {
482
- loc.addFormat(src);
483
- });
484
-
485
- return Localizations[localeCode] = loc;
486
- }
487
-
488
-
489
- // General helpers
490
-
491
- function addDateInputFormat(locale, format, match, variant) {
492
- locale.compiledFormats.unshift({
493
- variant: variant,
494
- locale: locale,
495
- reg: regexp('^' + format + '$', 'i'),
496
- to: match
497
- });
498
- }
499
-
500
- function simpleCapitalize(str) {
501
- return str.slice(0,1).toUpperCase() + str.slice(1);
502
- }
503
-
504
- function arrayToAlternates(arr) {
505
- return arr.filter(function(el) {
506
- return !!el;
507
- }).join('|');
508
- }
509
-
510
- // Date argument helpers
511
-
512
- function collectDateArguments(args, allowDuration) {
513
- var obj, arr;
514
- if(isObject(args[0])) {
515
- return args;
516
- } else if (isNumber(args[0]) && !isNumber(args[1])) {
517
- return [args[0]];
518
- } else if (isString(args[0]) && allowDuration) {
519
- return [getDateParamsFromString(args[0]), args[1]];
520
- }
521
- obj = {};
522
- DateArgumentUnits.forEach(function(u,i) {
523
- obj[u.unit] = args[i];
524
- });
525
- return [obj];
526
- }
527
-
528
- function getDateParamsFromString(str, num) {
529
- var params = {};
530
- match = str.match(/^(\d+)?\s?(\w+?)s?$/i);
531
- if(match) {
532
- if(isUndefined(num)) {
533
- num = parseInt(match[1]) || 1;
534
- }
535
- params[match[2].toLowerCase()] = num;
536
- }
537
- return params;
538
- }
539
-
540
- // Date parsing helpers
541
-
542
- function getFormatMatch(match, arr) {
543
- var obj = {}, value, num;
544
- arr.forEach(function(key, i) {
545
- value = match[i + 1];
546
- if(isUndefined(value) || value === '') return;
547
- if(key === 'year') {
548
- obj.yearAsString = value.replace(/'/, '');
549
- }
550
- num = parseFloat(value.replace(/'/, '').replace(/,/, '.'));
551
- obj[key] = !isNaN(num) ? num : value.toLowerCase();
552
- });
553
- return obj;
554
- }
555
-
556
- function cleanDateInput(str) {
557
- str = str.trim().replace(/^(just )?now|\.+$/i, '');
558
- return convertAsianDigits(str);
559
- }
560
-
561
- function convertAsianDigits(str) {
562
- return str.replace(AsianDigitReg, function(full, disallowed, match) {
563
- var sum = 0, place = 1, lastWasHolder, lastHolder;
564
- if(disallowed) return full;
565
- match.split('').reverse().forEach(function(letter) {
566
- var value = AsianDigitMap[letter], holder = value > 9;
567
- if(holder) {
568
- if(lastWasHolder) sum += place;
569
- place *= value / (lastHolder || 1);
570
- lastHolder = value;
571
- } else {
572
- if(lastWasHolder === false) {
573
- place *= 10;
574
- }
575
- sum += place * value;
576
- }
577
- lastWasHolder = holder;
578
- });
579
- if(lastWasHolder) sum += place;
580
- return sum;
581
- });
582
- }
583
-
584
- function getExtendedDate(f, localeCode, prefer, forceUTC) {
585
- var d = new date(), relative = false, baseLocalization, loc, format, set, unit, weekday, num, tmp, after;
586
-
587
- d.utc(forceUTC);
588
-
589
- if(isDate(f)) {
590
- // If the source here is already a date object, then the operation
591
- // is the same as cloning the date, which preserves the UTC flag.
592
- d.utc(f.isUTC()).setTime(f.getTime());
593
- } else if(isNumber(f)) {
594
- d.setTime(f);
595
- } else if(isObject(f)) {
596
- d.set(f, true);
597
- set = f;
598
- } else if(isString(f)) {
599
-
600
- // The act of getting the localization will pre-initialize
601
- // if it is missing and add the required formats.
602
- baseLocalization = getLocalization(localeCode);
603
-
604
- // Clean the input and convert Kanji based numerals if they exist.
605
- f = cleanDateInput(f);
606
-
607
- if(baseLocalization) {
608
- iterateOverObject(baseLocalization.getFormats(), function(i, dif) {
609
- var match = f.match(dif.reg);
610
- if(match) {
611
- format = dif;
612
- loc = format.locale;
613
- set = getFormatMatch(match, format.to, loc);
614
-
615
- if(set['utc']) {
616
- d.utc();
617
- }
618
-
619
- loc.cachedFormat = format;
620
-
621
- if(set.timestamp) {
622
- set = set.timestamp;
623
- return false;
624
- }
625
-
626
- // If there's a variant (crazy Endian American format), swap the month and day.
627
- if(format.variant && !isString(set['month']) && (isString(set['date']) || baseLocalization.hasVariant(localeCode))) {
628
- tmp = set['month'];
629
- set['month'] = set['date'];
630
- set['date'] = tmp;
631
- }
632
-
633
- // If the year is 2 digits then get the implied century.
634
- if(set['year'] && set.yearAsString.length === 2) {
635
- set['year'] = getYearFromAbbreviation(set['year']);
636
- }
637
-
638
- // Set the month which may be localized.
639
- if(set['month']) {
640
- set['month'] = loc.getMonth(set['month']);
641
- if(set['shift'] && !set['unit']) set['unit'] = loc['units'][7];
642
- }
643
-
644
- // If there is both a weekday and a date, the date takes precedence.
645
- if(set['weekday'] && set['date']) {
646
- delete set['weekday'];
647
- // Otherwise set a localized weekday.
648
- } else if(set['weekday']) {
649
- set['weekday'] = loc.getWeekday(set['weekday']);
650
- if(set['shift'] && !set['unit']) set['unit'] = loc['units'][5];
651
- }
652
-
653
- // Relative day localizations such as "today" and "tomorrow".
654
- if(set['day'] && (tmp = loc.modifiersByName[set['day']])) {
655
- set['day'] = tmp.value;
656
- d.reset();
657
- relative = true;
658
- // If the day is a weekday, then set that instead.
659
- } else if(set['day'] && (weekday = loc.getWeekday(set['day'])) > -1) {
660
- delete set['day'];
661
- if(set['num'] && set['month']) {
662
- // If we have "the 2nd tuesday of June", set the day to the beginning of the month, then
663
- // look ahead to set the weekday after all other properties have been set. The weekday needs
664
- // to be set after the actual set because it requires overriding the "prefer" argument which
665
- // could unintentionally send the year into the future, past, etc.
666
- after = function() {
667
- var w = d.getWeekday();
668
- d.setWeekday((7 * (set['num'] - 1)) + (w > weekday ? weekday + 7 : weekday));
669
- }
670
- set['day'] = 1;
671
- } else {
672
- set['weekday'] = weekday;
673
- }
674
- }
675
-
676
- if(set['date'] && !isNumber(set['date'])) {
677
- set['date'] = loc.getNumericDate(set['date']);
678
- }
679
-
680
- // If the time is 1pm-11pm advance the time by 12 hours.
681
- if(loc.matchPM(set['ampm']) && set['hour'] < 12) {
682
- set['hour'] += 12;
683
- } else if(loc.matchAM(set['ampm']) && set['hour'] === 12) {
684
- set['hour'] = 0;
685
- }
686
-
687
- // Adjust for timezone offset
688
- if('offset_hours' in set || 'offset_minutes' in set) {
689
- d.utc();
690
- set['offset_minutes'] = set['offset_minutes'] || 0;
691
- set['offset_minutes'] += set['offset_hours'] * 60;
692
- if(set['offset_sign'] === '-') {
693
- set['offset_minutes'] *= -1;
694
- }
695
- set['minute'] -= set['offset_minutes'];
696
- }
697
-
698
- // Date has a unit like "days", "months", etc. are all relative to the current date.
699
- if(set['unit']) {
700
- relative = true;
701
- num = loc.getNumber(set['num']);
702
- unit = loc.getEnglishUnit(set['unit']);
703
-
704
- // Shift and unit, ie "next month", "last week", etc.
705
- if(set['shift'] || set['edge']) {
706
- num *= (tmp = loc.modifiersByName[set['shift']]) ? tmp.value : 0;
707
-
708
- // Relative month and static date: "the 15th of last month"
709
- if(unit === 'month' && isDefined(set['date'])) {
710
- d.set({ 'day': set['date'] }, true);
711
- delete set['date'];
712
- }
713
-
714
- // Relative year and static month/date: "June 15th of last year"
715
- if(unit === 'year' && isDefined(set['month'])) {
716
- d.set({ 'month': set['month'], 'day': set['date'] }, true);
717
- delete set['month'];
718
- delete set['date'];
719
- }
720
- }
721
- // Unit and sign, ie "months ago", "weeks from now", etc.
722
- if(set['sign'] && (tmp = loc.modifiersByName[set['sign']])) {
723
- num *= tmp.value;
724
- }
725
-
726
- // Units can be with non-relative dates, set here. ie "the day after monday"
727
- if(isDefined(set['weekday'])) {
728
- d.set({'weekday': set['weekday'] }, true);
729
- delete set['weekday'];
730
- }
731
-
732
- // Finally shift the unit.
733
- set[unit] = (set[unit] || 0) + num;
734
- }
735
-
736
- if(set['year_sign'] === '-') {
737
- set['year'] *= -1;
738
- }
739
-
740
- DateUnitsReversed.slice(1,4).forEach(function(u, i) {
741
- var value = set[u.unit], fraction = value % 1;
742
- if(fraction) {
743
- set[DateUnitsReversed[i].unit] = round(fraction * (u.unit === 'second' ? 1000 : 60));
744
- set[u.unit] = floor(value);
745
- }
746
- });
747
- return false;
748
- }
749
- });
750
- }
751
- if(!format) {
752
- // The Date constructor does something tricky like checking the number
753
- // of arguments so simply passing in undefined won't work.
754
- d = f ? new date(f) : new date();
755
- if(forceUTC) {
756
- // Falling back to system date here which cannot be parsed as UTC,
757
- // so if we're forcing UTC then simply add the offset.
758
- d.addMinutes(d.getTimezoneOffset());
759
- }
760
- } else if(relative) {
761
- d.advance(set);
762
- } else {
763
- if(d._utc) {
764
- // UTC times can traverse into other days or even months,
765
- // so preemtively reset the time here to prevent this.
766
- d.reset();
767
- }
768
- updateDate(d, set, true, false, prefer);
769
- }
770
-
771
- // If there is an "edge" it needs to be set after the
772
- // other fields are set. ie "the end of February"
773
- if(set && set['edge']) {
774
- tmp = loc.modifiersByName[set['edge']];
775
- iterateOverObject(DateUnitsReversed.slice(4), function(i, u) {
776
- if(isDefined(set[u.unit])) {
777
- unit = u.unit;
778
- return false;
779
- }
780
- });
781
- if(unit === 'year') set.specificity = 'month';
782
- else if(unit === 'month' || unit === 'week') set.specificity = 'day';
783
- d[(tmp.value < 0 ? 'endOf' : 'beginningOf') + simpleCapitalize(unit)]();
784
- // This value of -2 is arbitrary but it's a nice clean way to hook into this system.
785
- if(tmp.value === -2) d.reset();
786
- }
787
- if(after) {
788
- after();
789
- }
790
- // A date created by parsing a string presumes that the format *itself* is UTC, but
791
- // not that the date, once created, should be manipulated as such. In other words,
792
- // if you are creating a date object from a server time "2012-11-15T12:00:00Z",
793
- // in the majority of cases you are using it to create a date that will, after creation,
794
- // be manipulated as local, so reset the utc flag here.
795
- d.utc(false);
796
- }
797
- return {
798
- date: d,
799
- set: set
800
- }
801
- }
802
-
803
- // If the year is two digits, add the most appropriate century prefix.
804
- function getYearFromAbbreviation(year) {
805
- return round(callDateGet(new date(), 'FullYear') / 100) * 100 - round(year / 100) * 100 + year;
806
- }
807
-
808
- function getShortHour(d) {
809
- var hours = callDateGet(d, 'Hours');
810
- return hours === 0 ? 12 : hours - (floor(hours / 13) * 12);
811
- }
812
-
813
- // weeksSince won't work here as the result needs to be floored, not rounded.
814
- function getWeekNumber(date) {
815
- date = date.clone();
816
- var dow = callDateGet(date, 'Day') || 7;
817
- date.addDays(4 - dow).reset();
818
- return 1 + floor(date.daysSince(date.clone().beginningOfYear()) / 7);
819
- }
820
-
821
- function getAdjustedUnit(ms) {
822
- var next, ams = math.abs(ms), value = ams, unit = 0;
823
- DateUnitsReversed.slice(1).forEach(function(u, i) {
824
- next = floor(round(ams / u.multiplier() * 10) / 10);
825
- if(next >= 1) {
826
- value = next;
827
- unit = i + 1;
828
- }
829
- });
830
- return [value, unit, ms];
831
- }
832
-
833
-
834
- // Date formatting helpers
835
-
836
- function formatDate(date, format, relative, localeCode) {
837
- var adu, loc = getLocalization(localeCode), caps = regexp(/^[A-Z]/), value, shortcut;
838
- if(!date.isValid()) {
839
- return 'Invalid Date';
840
- } else if(Date[format]) {
841
- format = Date[format];
842
- } else if(isFunction(format)) {
843
- adu = getAdjustedUnit(date.millisecondsFromNow());
844
- format = format.apply(date, adu.concat(loc));
845
- }
846
- if(!format && relative) {
847
- adu = adu || getAdjustedUnit(date.millisecondsFromNow());
848
- // Adjust up if time is in ms, as this doesn't
849
- // look very good for a standard relative date.
850
- if(adu[1] === 0) {
851
- adu[1] = 1;
852
- adu[0] = 1;
853
- }
854
- return loc.getRelativeFormat(adu);
855
- }
856
-
857
- format = format || 'long';
858
- format = loc[format] || format;
859
-
860
- DateOutputFormats.forEach(function(dof) {
861
- format = format.replace(regexp('\\{('+dof.token+')(\\d)?\\}', dof.word ? 'i' : ''), function(m,t,d) {
862
- var val = dof.format(date, loc, d || 1, t), l = t.length, one = t.match(/^(.)\1+$/);
863
- if(dof.word) {
864
- if(l === 3) val = val.slice(0,3);
865
- if(one || t.match(caps)) val = simpleCapitalize(val);
866
- } else if(one && !dof.text) {
867
- val = (isNumber(val) ? padNumber(val, l) : val.toString()).slice(-l);
868
- }
869
- return val;
870
- });
871
- });
872
- return format;
873
- }
874
-
875
- // Date comparison helpers
876
-
877
- function compareDate(d, find, buffer, forceUTC) {
878
- var p, t, min, max, minOffset, maxOffset, override, capitalized, accuracy = 0, loBuffer = 0, hiBuffer = 0;
879
- p = getExtendedDate(find, null, null, forceUTC);
880
- if(buffer > 0) {
881
- loBuffer = hiBuffer = buffer;
882
- override = true;
883
- }
884
- if(!p.date.isValid()) return false;
885
- if(p.set && p.set.specificity) {
886
- DateUnits.forEach(function(u, i) {
887
- if(u.unit === p.set.specificity) {
888
- accuracy = u.multiplier(p.date, d - p.date) - 1;
889
- }
890
- });
891
- capitalized = simpleCapitalize(p.set.specificity);
892
- if(p.set['edge'] || p.set['shift']) {
893
- p.date['beginningOf' + capitalized]();
894
- }
895
- if(p.set.specificity === 'month') {
896
- max = p.date.clone()['endOf' + capitalized]().getTime();
897
- }
898
- if(!override && p.set['sign'] && p.set.specificity != 'millisecond') {
899
- // If the time is relative, there can occasionally be an disparity between the relative date
900
- // and "now", which it is being compared to, so set an extra buffer to account for this.
901
- loBuffer = 50;
902
- hiBuffer = -50;
903
- }
904
- }
905
- t = d.getTime();
906
- min = p.date.getTime();
907
- max = max || (min + accuracy);
908
- max = compensateForTimezoneTraversal(d, min, max);
909
- return t >= (min - loBuffer) && t <= (max + hiBuffer);
910
- }
911
-
912
- function compensateForTimezoneTraversal(d, min, max) {
913
- var dMin, dMax, minOffset, maxOffset;
914
- dMin = new Date(min);
915
- dMax = new Date(max).utc(d.isUTC());
916
- if(callDateGet(dMax, 'Hours') !== 23) {
917
- minOffset = dMin.getTimezoneOffset();
918
- maxOffset = dMax.getTimezoneOffset();
919
- if(minOffset !== maxOffset) {
920
- max += (maxOffset - minOffset).minutes();
921
- }
922
- }
923
- return max;
924
- }
925
-
926
- function updateDate(d, params, reset, advance, prefer) {
927
- var weekday, specificityIndex;
928
-
929
- function getParam(key) {
930
- return isDefined(params[key]) ? params[key] : params[key + 's'];
931
- }
932
-
933
- function paramExists(key) {
934
- return isDefined(getParam(key));
935
- }
936
-
937
- function uniqueParamExists(key, isDay) {
938
- return paramExists(key) || (isDay && paramExists('weekday'));
939
- }
940
-
941
- function canDisambiguate() {
942
- var now = new date;
943
- return (prefer === -1 && d > now) || (prefer === 1 && d < now);
944
- }
945
-
946
- if(isNumber(params) && advance) {
947
- // If param is a number and we're advancing, the number is presumed to be milliseconds.
948
- params = { 'milliseconds': params };
949
- } else if(isNumber(params)) {
950
- // Otherwise just set the timestamp and return.
951
- d.setTime(params);
952
- return d;
953
- }
954
-
955
- // "date" can also be passed for the day
956
- if(isDefined(params['date'])) {
957
- params['day'] = params['date'];
958
- }
959
-
960
- // Reset any unit lower than the least specific unit set. Do not do this for weeks
961
- // or for years. This needs to be performed before the acutal setting of the date
962
- // because the order needs to be reversed in order to get the lowest specificity,
963
- // also because higher order units can be overwritten by lower order units, such
964
- // as setting hour: 3, minute: 345, etc.
965
- iterateOverObject(DateUnitsReversed, function(i,u) {
966
- var isDay = u.unit === 'day';
967
- if(uniqueParamExists(u.unit, isDay)) {
968
- params.specificity = u.unit;
969
- specificityIndex = +i;
970
- return false;
971
- } else if(reset && u.unit !== 'week' && (!isDay || !paramExists('week'))) {
972
- // Days are relative to months, not weeks, so don't reset if a week exists.
973
- callDateSet(d, u.method, (isDay ? 1 : 0));
974
- }
975
- });
976
-
977
-
978
- // Now actually set or advance the date in order, higher units first.
979
- DateUnits.forEach(function(u,i) {
980
- var unit = u.unit, method = u.method, higherUnit = DateUnits[i - 1], value;
981
- value = getParam(unit)
982
- if(isUndefined(value)) return;
983
- if(advance) {
984
- if(unit === 'week') {
985
- value = (params['day'] || 0) + (value * 7);
986
- method = 'Date';
987
- }
988
- value = (value * advance) + callDateGet(d, method);
989
- } else if(unit === 'month' && paramExists('day')) {
990
- // When setting the month, there is a chance that we will traverse into a new month.
991
- // This happens in DST shifts, for example June 1st DST jumping to January 1st
992
- // (non-DST) will have a shift of -1:00 which will traverse into the previous year.
993
- // Prevent this by proactively setting the day when we know it will be set again anyway.
994
- // It can also happen when there are not enough days in the target month. This second
995
- // situation is identical to checkMonthTraversal below, however when we are advancing
996
- // we want to reset the date to "the last date in the target month". In the case of
997
- // DST shifts, however, we want to avoid the "edges" of months as that is where this
998
- // unintended traversal can happen. This is the reason for the different handling of
999
- // two similar but slightly different situations.
1000
- //
1001
- // TL;DR This method avoids the edges of a month IF not advancing and the date is going
1002
- // to be set anyway, while checkMonthTraversal resets the date to the last day if advancing.
1003
- //
1004
- callDateSet(d, 'Date', 15);
1005
- }
1006
- callDateSet(d, method, value);
1007
- if(advance && unit === 'month') {
1008
- checkMonthTraversal(d, value);
1009
- }
1010
- });
1011
-
1012
-
1013
- // If a weekday is included in the params, set it ahead of time and set the params
1014
- // to reflect the updated date so that resetting works properly.
1015
- if(!advance && !paramExists('day') && paramExists('weekday')) {
1016
- var weekday = getParam('weekday'), isAhead, futurePreferred;
1017
- d.setWeekday(weekday);
1018
- }
1019
-
1020
- if(canDisambiguate()) {
1021
- iterateOverObject(DateUnitsReversed.slice(specificityIndex + 1), function(i,u) {
1022
- var ambiguous = u.ambiguous || (u.unit === 'week' && paramExists('weekday'));
1023
- if(ambiguous && !uniqueParamExists(u.unit, u.unit === 'day')) {
1024
- d[u.addMethod](prefer);
1025
- return false;
1026
- }
1027
- });
1028
- }
1029
- return d;
1030
- }
1031
-
1032
- function callDateGet(d, method) {
1033
- return d['get' + (d._utc ? 'UTC' : '') + method]();
1034
- }
1035
-
1036
- function callDateSet(d, method, value) {
1037
- return d['set' + (d._utc ? 'UTC' : '') + method](value);
1038
- }
1039
-
1040
- // The ISO format allows times strung together without a demarcating ":", so make sure
1041
- // that these markers are now optional.
1042
- function prepareTime(format, loc, iso) {
1043
- var timeSuffixMapping = {'h':0,'m':1,'s':2}, add;
1044
- loc = loc || English;
1045
- return format.replace(/{([a-z])}/g, function(full, token) {
1046
- var separators = [],
1047
- isHours = token === 'h',
1048
- tokenIsRequired = isHours && !iso;
1049
- if(token === 't') {
1050
- return loc['ampm'].join('|');
1051
- } else {
1052
- if(isHours) {
1053
- separators.push(':');
1054
- }
1055
- if(add = loc['timeSuffixes'][timeSuffixMapping[token]]) {
1056
- separators.push(add + '\\s*');
1057
- }
1058
- return separators.length === 0 ? '' : '(?:' + separators.join('|') + ')' + (tokenIsRequired ? '' : '?');
1059
- }
1060
- });
1061
- }
1062
-
1063
-
1064
- // If the month is being set, then we don't want to accidentally
1065
- // traverse into a new month just because the target month doesn't have enough
1066
- // days. In other words, "5 months ago" from July 30th is still February, even
1067
- // though there is no February 30th, so it will of necessity be February 28th
1068
- // (or 29th in the case of a leap year).
1069
-
1070
- function checkMonthTraversal(date, targetMonth) {
1071
- if(targetMonth < 0) {
1072
- targetMonth = targetMonth % 12 + 12;
1073
- }
1074
- if(targetMonth % 12 != callDateGet(date, 'Month')) {
1075
- callDateSet(date, 'Date', 0);
1076
- }
1077
- }
1078
-
1079
- function createDate(args, prefer, forceUTC) {
1080
- var f, localeCode;
1081
- if(isNumber(args[1])) {
1082
- // If the second argument is a number, then we have an enumerated constructor type as in "new Date(2003, 2, 12);"
1083
- f = collectDateArguments(args)[0];
1084
- } else {
1085
- f = args[0];
1086
- localeCode = args[1];
1087
- }
1088
- return getExtendedDate(f, localeCode, prefer, forceUTC).date;
1089
- }
1090
-
1091
- function buildDateUnits() {
1092
- DateUnitsReversed = DateUnits.concat().reverse();
1093
- DateArgumentUnits = DateUnits.concat();
1094
- DateArgumentUnits.splice(2,1);
1095
- }
1096
-
1097
-
1098
- /***
1099
- * @method [units]Since([d], [locale] = currentLocale)
1100
- * @returns Number
1101
- * @short Returns the time since [d] in the appropriate unit.
1102
- * @extra [d] will accept a date object, timestamp, or text format. If not specified, [d] is assumed to be now. [locale] can be passed to specify the locale that the date is in. %[unit]Ago% is provided as an alias to make this more readable when [d] is assumed to be the current date. For more see @date_format.
1103
- *
1104
- * @set
1105
- * millisecondsSince
1106
- * secondsSince
1107
- * minutesSince
1108
- * hoursSince
1109
- * daysSince
1110
- * weeksSince
1111
- * monthsSince
1112
- * yearsSince
1113
- *
1114
- * @example
1115
- *
1116
- * Date.create().millisecondsSince('1 hour ago') -> 3,600,000
1117
- * Date.create().daysSince('1 week ago') -> 7
1118
- * Date.create().yearsSince('15 years ago') -> 15
1119
- * Date.create('15 years ago').yearsAgo() -> 15
1120
- *
1121
- ***
1122
- * @method [units]Ago()
1123
- * @returns Number
1124
- * @short Returns the time ago in the appropriate unit.
1125
- *
1126
- * @set
1127
- * millisecondsAgo
1128
- * secondsAgo
1129
- * minutesAgo
1130
- * hoursAgo
1131
- * daysAgo
1132
- * weeksAgo
1133
- * monthsAgo
1134
- * yearsAgo
1135
- *
1136
- * @example
1137
- *
1138
- * Date.create('last year').millisecondsAgo() -> 3,600,000
1139
- * Date.create('last year').daysAgo() -> 7
1140
- * Date.create('last year').yearsAgo() -> 15
1141
- *
1142
- ***
1143
- * @method [units]Until([d], [locale] = currentLocale)
1144
- * @returns Number
1145
- * @short Returns the time until [d] in the appropriate unit.
1146
- * @extra [d] will accept a date object, timestamp, or text format. If not specified, [d] is assumed to be now. [locale] can be passed to specify the locale that the date is in. %[unit]FromNow% is provided as an alias to make this more readable when [d] is assumed to be the current date. For more see @date_format.
1147
- *
1148
- * @set
1149
- * millisecondsUntil
1150
- * secondsUntil
1151
- * minutesUntil
1152
- * hoursUntil
1153
- * daysUntil
1154
- * weeksUntil
1155
- * monthsUntil
1156
- * yearsUntil
1157
- *
1158
- * @example
1159
- *
1160
- * Date.create().millisecondsUntil('1 hour from now') -> 3,600,000
1161
- * Date.create().daysUntil('1 week from now') -> 7
1162
- * Date.create().yearsUntil('15 years from now') -> 15
1163
- * Date.create('15 years from now').yearsFromNow() -> 15
1164
- *
1165
- ***
1166
- * @method [units]FromNow()
1167
- * @returns Number
1168
- * @short Returns the time from now in the appropriate unit.
1169
- *
1170
- * @set
1171
- * millisecondsFromNow
1172
- * secondsFromNow
1173
- * minutesFromNow
1174
- * hoursFromNow
1175
- * daysFromNow
1176
- * weeksFromNow
1177
- * monthsFromNow
1178
- * yearsFromNow
1179
- *
1180
- * @example
1181
- *
1182
- * Date.create('next year').millisecondsFromNow() -> 3,600,000
1183
- * Date.create('next year').daysFromNow() -> 7
1184
- * Date.create('next year').yearsFromNow() -> 15
1185
- *
1186
- ***
1187
- * @method add[Units](<num>, [reset] = false)
1188
- * @returns Date
1189
- * @short Adds <num> of the unit to the date. If [reset] is true, all lower units will be reset.
1190
- * @extra Note that "months" is ambiguous as a unit of time. If the target date falls on a day that does not exist (ie. August 31 -> February 31), the date will be shifted to the last day of the month. Don't use %addMonths% if you need precision.
1191
- *
1192
- * @set
1193
- * addMilliseconds
1194
- * addSeconds
1195
- * addMinutes
1196
- * addHours
1197
- * addDays
1198
- * addWeeks
1199
- * addMonths
1200
- * addYears
1201
- *
1202
- * @example
1203
- *
1204
- * Date.create().addMilliseconds(5) -> current time + 5 milliseconds
1205
- * Date.create().addDays(5) -> current time + 5 days
1206
- * Date.create().addYears(5) -> current time + 5 years
1207
- *
1208
- ***
1209
- * @method isLast[Unit]()
1210
- * @returns Boolean
1211
- * @short Returns true if the date is last week/month/year.
1212
- *
1213
- * @set
1214
- * isLastWeek
1215
- * isLastMonth
1216
- * isLastYear
1217
- *
1218
- * @example
1219
- *
1220
- * Date.create('yesterday').isLastWeek() -> true or false?
1221
- * Date.create('yesterday').isLastMonth() -> probably not...
1222
- * Date.create('yesterday').isLastYear() -> even less likely...
1223
- *
1224
- ***
1225
- * @method isThis[Unit]()
1226
- * @returns Boolean
1227
- * @short Returns true if the date is this week/month/year.
1228
- *
1229
- * @set
1230
- * isThisWeek
1231
- * isThisMonth
1232
- * isThisYear
1233
- *
1234
- * @example
1235
- *
1236
- * Date.create('tomorrow').isThisWeek() -> true or false?
1237
- * Date.create('tomorrow').isThisMonth() -> probably...
1238
- * Date.create('tomorrow').isThisYear() -> signs point to yes...
1239
- *
1240
- ***
1241
- * @method isNext[Unit]()
1242
- * @returns Boolean
1243
- * @short Returns true if the date is next week/month/year.
1244
- *
1245
- * @set
1246
- * isNextWeek
1247
- * isNextMonth
1248
- * isNextYear
1249
- *
1250
- * @example
1251
- *
1252
- * Date.create('tomorrow').isNextWeek() -> true or false?
1253
- * Date.create('tomorrow').isNextMonth() -> probably not...
1254
- * Date.create('tomorrow').isNextYear() -> even less likely...
1255
- *
1256
- ***
1257
- * @method beginningOf[Unit]()
1258
- * @returns Date
1259
- * @short Sets the date to the beginning of the appropriate unit.
1260
- *
1261
- * @set
1262
- * beginningOfDay
1263
- * beginningOfWeek
1264
- * beginningOfMonth
1265
- * beginningOfYear
1266
- *
1267
- * @example
1268
- *
1269
- * Date.create().beginningOfDay() -> the beginning of today (resets the time)
1270
- * Date.create().beginningOfWeek() -> the beginning of the week
1271
- * Date.create().beginningOfMonth() -> the beginning of the month
1272
- * Date.create().beginningOfYear() -> the beginning of the year
1273
- *
1274
- ***
1275
- * @method endOf[Unit]()
1276
- * @returns Date
1277
- * @short Sets the date to the end of the appropriate unit.
1278
- *
1279
- * @set
1280
- * endOfDay
1281
- * endOfWeek
1282
- * endOfMonth
1283
- * endOfYear
1284
- *
1285
- * @example
1286
- *
1287
- * Date.create().endOfDay() -> the end of today (sets the time to 23:59:59.999)
1288
- * Date.create().endOfWeek() -> the end of the week
1289
- * Date.create().endOfMonth() -> the end of the month
1290
- * Date.create().endOfYear() -> the end of the year
1291
- *
1292
- ***/
1293
-
1294
- function buildDateMethods() {
1295
- extendSimilar(date, true, false, DateUnits, function(methods, u, i) {
1296
- var unit = u.unit, caps = simpleCapitalize(unit), multiplier = u.multiplier(), since, until;
1297
- u.addMethod = 'add' + caps + 's';
1298
- // "since/until now" only count "past" an integer, i.e. "2 days ago" is
1299
- // anything between 2 - 2.999 days. The default margin of error is 0.999,
1300
- // but "months" have an inherently larger margin, as the number of days
1301
- // in a given month may be significantly less than the number of days in
1302
- // the average month, so for example "30 days" before March 15 may in fact
1303
- // be 1 month ago. Years also have a margin of error due to leap years,
1304
- // but this is roughly 0.999 anyway (365 / 365.25). Other units do not
1305
- // technically need the error margin applied to them but this accounts
1306
- // for discrepancies like (15).hoursAgo() which technically creates the
1307
- // current date first, then creates a date 15 hours before and compares
1308
- // them, the discrepancy between the creation of the 2 dates means that
1309
- // they may actually be 15.0001 hours apart. Milliseconds don't have
1310
- // fractions, so they won't be subject to this error margin.
1311
- function applyErrorMargin(ms) {
1312
- var num = ms / multiplier,
1313
- fraction = num % 1,
1314
- error = u.error || 0.999;
1315
- if(fraction && math.abs(fraction % 1) > error) {
1316
- num = round(num);
1317
- }
1318
- return parseInt(num);
1319
- }
1320
- since = function(f, localeCode) {
1321
- return applyErrorMargin(this.getTime() - date.create(f, localeCode).getTime());
1322
- };
1323
- until = function(f, localeCode) {
1324
- return applyErrorMargin(date.create(f, localeCode).getTime() - this.getTime());
1325
- };
1326
- methods[unit+'sAgo'] = until;
1327
- methods[unit+'sUntil'] = until;
1328
- methods[unit+'sSince'] = since;
1329
- methods[unit+'sFromNow'] = since;
1330
- methods[u.addMethod] = function(num, reset) {
1331
- var set = {};
1332
- set[unit] = num;
1333
- return this.advance(set, reset);
1334
- };
1335
- buildNumberToDateAlias(u, multiplier);
1336
- if(i < 3) {
1337
- ['Last','This','Next'].forEach(function(shift) {
1338
- methods['is' + shift + caps] = function() {
1339
- return this.is(shift + ' ' + unit);
1340
- };
1341
- });
1342
- }
1343
- if(i < 4) {
1344
- methods['beginningOf' + caps] = function() {
1345
- var set = {};
1346
- switch(unit) {
1347
- case 'year': set['year'] = callDateGet(this, 'FullYear'); break;
1348
- case 'month': set['month'] = callDateGet(this, 'Month'); break;
1349
- case 'day': set['day'] = callDateGet(this, 'Date'); break;
1350
- case 'week': set['weekday'] = 0; break;
1351
- }
1352
- return this.set(set, true);
1353
- };
1354
- methods['endOf' + caps] = function() {
1355
- var set = { 'hours': 23, 'minutes': 59, 'seconds': 59, 'milliseconds': 999 };
1356
- switch(unit) {
1357
- case 'year': set['month'] = 11; set['day'] = 31; break;
1358
- case 'month': set['day'] = this.daysInMonth(); break;
1359
- case 'week': set['weekday'] = 6; break;
1360
- }
1361
- return this.set(set, true);
1362
- };
1363
- }
1364
- });
1365
- }
1366
-
1367
- function buildCoreInputFormats() {
1368
- English.addFormat('([+-])?(\\d{4,4})[-.]?{full_month}[-.]?(\\d{1,2})?', true, ['year_sign','year','month','date'], false, true);
1369
- English.addFormat('(\\d{1,2})[-.\\/]{full_month}(?:[-.\\/](\\d{2,4}))?', true, ['date','month','year'], true);
1370
- English.addFormat('{full_month}[-.](\\d{4,4})', false, ['month','year']);
1371
- English.addFormat('\\/Date\\((\\d+(?:\\+\\d{4,4})?)\\)\\/', false, ['timestamp'])
1372
- English.addFormat(prepareTime(RequiredTime, English), false, TimeFormat)
1373
-
1374
- // When a new locale is initialized it will have the CoreDateFormats initialized by default.
1375
- // From there, adding new formats will push them in front of the previous ones, so the core
1376
- // formats will be the last to be reached. However, the core formats themselves have English
1377
- // months in them, which means that English needs to first be initialized and creates a race
1378
- // condition. I'm getting around this here by adding these generalized formats in the order
1379
- // specific -> general, which will mean they will be added to the English localization in
1380
- // general -> specific order, then chopping them off the front and reversing to get the correct
1381
- // order. Note that there are 7 formats as 2 have times which adds a front and a back format.
1382
- CoreDateFormats = English.compiledFormats.slice(0,7).reverse();
1383
- English.compiledFormats = English.compiledFormats.slice(7).concat(CoreDateFormats);
1384
- }
1385
-
1386
- function buildDateOutputShortcuts() {
1387
- extendSimilar(date, true, false, 'short,long,full', function(methods, name) {
1388
- methods[name] = function(localeCode) {
1389
- return formatDate(this, name, false, localeCode);
1390
- }
1391
- });
1392
- }
1393
-
1394
- function buildAsianDigits() {
1395
- KanjiDigits.split('').forEach(function(digit, value) {
1396
- var holder;
1397
- if(value > 9) {
1398
- value = math.pow(10, value - 9);
1399
- }
1400
- AsianDigitMap[digit] = value;
1401
- });
1402
- FullWidthDigits.split('').forEach(function(digit, value) {
1403
- AsianDigitMap[digit] = value;
1404
- });
1405
- // Kanji numerals may also be included in phrases which are text-based rather
1406
- // than actual numbers such as Chinese weekdays (上周三), and "the day before
1407
- // yesterday" (一昨日) in Japanese, so don't match these.
1408
- AsianDigitReg = regexp('([期週周])?([' + KanjiDigits + FullWidthDigits + ']+)(?!昨)', 'g');
1409
- }
1410
-
1411
- /***
1412
- * @method is[Day]()
1413
- * @returns Boolean
1414
- * @short Returns true if the date falls on that day.
1415
- * @extra Also available: %isYesterday%, %isToday%, %isTomorrow%, %isWeekday%, and %isWeekend%.
1416
- *
1417
- * @set
1418
- * isToday
1419
- * isYesterday
1420
- * isTomorrow
1421
- * isWeekday
1422
- * isWeekend
1423
- * isSunday
1424
- * isMonday
1425
- * isTuesday
1426
- * isWednesday
1427
- * isThursday
1428
- * isFriday
1429
- * isSaturday
1430
- *
1431
- * @example
1432
- *
1433
- * Date.create('tomorrow').isToday() -> false
1434
- * Date.create('thursday').isTomorrow() -> ?
1435
- * Date.create('yesterday').isWednesday() -> ?
1436
- * Date.create('today').isWeekend() -> ?
1437
- *
1438
- ***
1439
- * @method isFuture()
1440
- * @returns Boolean
1441
- * @short Returns true if the date is in the future.
1442
- * @example
1443
- *
1444
- * Date.create('next week').isFuture() -> true
1445
- * Date.create('last week').isFuture() -> false
1446
- *
1447
- ***
1448
- * @method isPast()
1449
- * @returns Boolean
1450
- * @short Returns true if the date is in the past.
1451
- * @example
1452
- *
1453
- * Date.create('last week').isPast() -> true
1454
- * Date.create('next week').isPast() -> false
1455
- *
1456
- ***/
1457
- function buildRelativeAliases() {
1458
- var special = 'today,yesterday,tomorrow,weekday,weekend,future,past'.split(',');
1459
- var weekdays = English['weekdays'].slice(0,7);
1460
- var months = English['months'].slice(0,12);
1461
- extendSimilar(date, true, false, special.concat(weekdays).concat(months), function(methods, name) {
1462
- methods['is'+ simpleCapitalize(name)] = function(utc) {
1463
- return this.is(name, 0, utc);
1464
- };
1465
- });
1466
- }
1467
-
1468
- function buildUTCAliases() {
1469
- date.extend({
1470
- 'utc': {
1471
-
1472
- 'create': function() {
1473
- return createDate(arguments, 0, true);
1474
- },
1475
-
1476
- 'past': function() {
1477
- return createDate(arguments, -1, true);
1478
- },
1479
-
1480
- 'future': function() {
1481
- return createDate(arguments, 1, true);
1482
- }
1483
-
1484
- }
1485
- }, false, false);
1486
- }
1487
-
1488
- function setDateProperties() {
1489
- date.extend({
1490
- 'RFC1123': '{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}',
1491
- 'RFC1036': '{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}',
1492
- 'ISO8601_DATE': '{yyyy}-{MM}-{dd}',
1493
- 'ISO8601_DATETIME': '{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}'
1494
- }, false, false);
1495
- }
1496
-
1497
-
1498
- date.extend({
1499
-
1500
- /***
1501
- * @method Date.create(<d>, [locale] = currentLocale)
1502
- * @returns Date
1503
- * @short Alternate Date constructor which understands many different text formats, a timestamp, or another date.
1504
- * @extra If no argument is given, date is assumed to be now. %Date.create% additionally can accept enumerated parameters as with the standard date constructor. [locale] can be passed to specify the locale that the date is in. When unspecified, the current locale (default is English) is assumed. UTC-based dates can be created through the %utc% object. For more see @date_format.
1505
- * @set
1506
- * Date.utc.create
1507
- *
1508
- * @example
1509
- *
1510
- * Date.create('July') -> July of this year
1511
- * Date.create('1776') -> 1776
1512
- * Date.create('today') -> today
1513
- * Date.create('wednesday') -> This wednesday
1514
- * Date.create('next friday') -> Next friday
1515
- * Date.create('July 4, 1776') -> July 4, 1776
1516
- * Date.create(-446806800000) -> November 5, 1955
1517
- * Date.create(1776, 6, 4) -> July 4, 1776
1518
- * Date.create('1776年07月04日', 'ja') -> July 4, 1776
1519
- * Date.utc.create('July 4, 1776', 'en') -> July 4, 1776
1520
- *
1521
- ***/
1522
- 'create': function() {
1523
- return createDate(arguments);
1524
- },
1525
-
1526
- /***
1527
- * @method Date.past(<d>, [locale] = currentLocale)
1528
- * @returns Date
1529
- * @short Alternate form of %Date.create% with any ambiguity assumed to be the past.
1530
- * @extra For example %"Sunday"% can be either "the Sunday coming up" or "the Sunday last" depending on context. Note that dates explicitly in the future ("next Sunday") will remain in the future. This method simply provides a hint when ambiguity exists. UTC-based dates can be created through the %utc% object. For more, see @date_format.
1531
- * @set
1532
- * Date.utc.past
1533
- * @example
1534
- *
1535
- * Date.past('July') -> July of this year or last depending on the current month
1536
- * Date.past('Wednesday') -> This wednesday or last depending on the current weekday
1537
- *
1538
- ***/
1539
- 'past': function() {
1540
- return createDate(arguments, -1);
1541
- },
1542
-
1543
- /***
1544
- * @method Date.future(<d>, [locale] = currentLocale)
1545
- * @returns Date
1546
- * @short Alternate form of %Date.create% with any ambiguity assumed to be the future.
1547
- * @extra For example %"Sunday"% can be either "the Sunday coming up" or "the Sunday last" depending on context. Note that dates explicitly in the past ("last Sunday") will remain in the past. This method simply provides a hint when ambiguity exists. UTC-based dates can be created through the %utc% object. For more, see @date_format.
1548
- * @set
1549
- * Date.utc.future
1550
- *
1551
- * @example
1552
- *
1553
- * Date.future('July') -> July of this year or next depending on the current month
1554
- * Date.future('Wednesday') -> This wednesday or next depending on the current weekday
1555
- *
1556
- ***/
1557
- 'future': function() {
1558
- return createDate(arguments, 1);
1559
- },
1560
-
1561
- /***
1562
- * @method Date.addLocale(<code>, <set>)
1563
- * @returns Locale
1564
- * @short Adds a locale <set> to the locales understood by Sugar.
1565
- * @extra For more see @date_format.
1566
- *
1567
- ***/
1568
- 'addLocale': function(localeCode, set) {
1569
- return setLocalization(localeCode, set);
1570
- },
1571
-
1572
- /***
1573
- * @method Date.setLocale(<code>)
1574
- * @returns Locale
1575
- * @short Sets the current locale to be used with dates.
1576
- * @extra Sugar has support for 13 locales that are available through the "Date Locales" package. In addition you can define a new locale with %Date.addLocale%. For more see @date_format.
1577
- *
1578
- ***/
1579
- 'setLocale': function(localeCode, set) {
1580
- var loc = getLocalization(localeCode, false);
1581
- CurrentLocalization = loc;
1582
- // The code is allowed to be more specific than the codes which are required:
1583
- // i.e. zh-CN or en-US. Currently this only affects US date variants such as 8/10/2000.
1584
- if(localeCode && localeCode != loc['code']) {
1585
- loc['code'] = localeCode;
1586
- }
1587
- return loc;
1588
- },
1589
-
1590
- /***
1591
- * @method Date.getLocale([code] = current)
1592
- * @returns Locale
1593
- * @short Gets the locale for the given code, or the current locale.
1594
- * @extra The resulting locale object can be manipulated to provide more control over date localizations. For more about locales, see @date_format.
1595
- *
1596
- ***/
1597
- 'getLocale': function(localeCode) {
1598
- return !localeCode ? CurrentLocalization : getLocalization(localeCode, false);
1599
- },
1600
-
1601
- /**
1602
- * @method Date.addFormat(<format>, <match>, [code] = null)
1603
- * @returns Nothing
1604
- * @short Manually adds a new date input format.
1605
- * @extra This method allows fine grained control for alternate formats. <format> is a string that can have regex tokens inside. <match> is an array of the tokens that each regex capturing group will map to, for example %year%, %date%, etc. For more, see @date_format.
1606
- *
1607
- **/
1608
- 'addFormat': function(format, match, localeCode) {
1609
- addDateInputFormat(getLocalization(localeCode), format, match);
1610
- }
1611
-
1612
- }, false, false);
1613
-
1614
- date.extend({
1615
-
1616
- /***
1617
- * @method set(<set>, [reset] = false)
1618
- * @returns Date
1619
- * @short Sets the date object.
1620
- * @extra This method can accept multiple formats including a single number as a timestamp, an object, or enumerated parameters (as with the Date constructor). If [reset] is %true%, any units more specific than those passed will be reset.
1621
- *
1622
- * @example
1623
- *
1624
- * new Date().set({ year: 2011, month: 11, day: 31 }) -> December 31, 2011
1625
- * new Date().set(2011, 11, 31) -> December 31, 2011
1626
- * new Date().set(86400000) -> 1 day after Jan 1, 1970
1627
- * new Date().set({ year: 2004, month: 6 }, true) -> June 1, 2004, 00:00:00.000
1628
- *
1629
- ***/
1630
- 'set': function() {
1631
- var args = collectDateArguments(arguments);
1632
- return updateDate(this, args[0], args[1])
1633
- },
1634
-
1635
- /***
1636
- * @method setWeekday()
1637
- * @returns Nothing
1638
- * @short Sets the weekday of the date.
1639
- *
1640
- * @example
1641
- *
1642
- * d = new Date(); d.setWeekday(1); d; -> Monday of this week
1643
- * d = new Date(); d.setWeekday(6); d; -> Saturday of this week
1644
- *
1645
- ***/
1646
- 'setWeekday': function(dow) {
1647
- if(isUndefined(dow)) return;
1648
- return callDateSet(this, 'Date', callDateGet(this, 'Date') + dow - callDateGet(this, 'Day'));
1649
- },
1650
-
1651
- /***
1652
- * @method setWeek()
1653
- * @returns Nothing
1654
- * @short Sets the week (of the year).
1655
- *
1656
- * @example
1657
- *
1658
- * d = new Date(); d.setWeek(15); d; -> 15th week of the year
1659
- *
1660
- ***/
1661
- 'setWeek': function(week) {
1662
- if(isUndefined(week)) return;
1663
- var date = callDateGet(this, 'Date');
1664
- callDateSet(this, 'Month', 0);
1665
- callDateSet(this, 'Date', (week * 7) + 1);
1666
- return this.getTime();
1667
- },
1668
-
1669
- /***
1670
- * @method getWeek()
1671
- * @returns Number
1672
- * @short Gets the date's week (of the year).
1673
- * @extra If %utc% is set on the date, the week will be according to UTC time.
1674
- *
1675
- * @example
1676
- *
1677
- * new Date().getWeek() -> today's week of the year
1678
- *
1679
- ***/
1680
- 'getWeek': function() {
1681
- return getWeekNumber(this);
1682
- },
1683
-
1684
- /***
1685
- * @method getUTCOffset([iso])
1686
- * @returns String
1687
- * @short Returns a string representation of the offset from UTC time. If [iso] is true the offset will be in ISO8601 format.
1688
- * @example
1689
- *
1690
- * new Date().getUTCOffset() -> "+0900"
1691
- * new Date().getUTCOffset(true) -> "+09:00"
1692
- *
1693
- ***/
1694
- 'getUTCOffset': function(iso) {
1695
- var offset = this._utc ? 0 : this.getTimezoneOffset();
1696
- var colon = iso === true ? ':' : '';
1697
- if(!offset && iso) return 'Z';
1698
- return padNumber(round(-offset / 60), 2, true) + colon + padNumber(offset % 60, 2);
1699
- },
1700
-
1701
- /***
1702
- * @method utc([on] = true)
1703
- * @returns Date
1704
- * @short Sets the internal utc flag for the date. When on, UTC-based methods will be called internally.
1705
- * @extra For more see @date_format.
1706
- * @example
1707
- *
1708
- * new Date().utc(true)
1709
- * new Date().utc(false)
1710
- *
1711
- ***/
1712
- 'utc': function(set) {
1713
- defineProperty(this, '_utc', set === true || arguments.length === 0);
1714
- return this;
1715
- },
1716
-
1717
- /***
1718
- * @method isUTC()
1719
- * @returns Boolean
1720
- * @short Returns true if the date has no timezone offset.
1721
- * @extra This will also return true for utc-based dates (dates that have the %utc% method set true). Note that even if the utc flag is set, %getTimezoneOffset% will always report the same thing as Javascript always reports that based on the environment's locale.
1722
- * @example
1723
- *
1724
- * new Date().isUTC() -> true or false?
1725
- * new Date().utc(true).isUTC() -> true
1726
- *
1727
- ***/
1728
- 'isUTC': function() {
1729
- return !!this._utc || this.getTimezoneOffset() === 0;
1730
- },
1731
-
1732
- /***
1733
- * @method advance(<set>, [reset] = false)
1734
- * @returns Date
1735
- * @short Sets the date forward.
1736
- * @extra This method can accept multiple formats including an object, a string in the format %3 days%, a single number as milliseconds, or enumerated parameters (as with the Date constructor). If [reset] is %true%, any units more specific than those passed will be reset. For more see @date_format.
1737
- * @example
1738
- *
1739
- * new Date().advance({ year: 2 }) -> 2 years in the future
1740
- * new Date().advance('2 days') -> 2 days in the future
1741
- * new Date().advance(0, 2, 3) -> 2 months 3 days in the future
1742
- * new Date().advance(86400000) -> 1 day in the future
1743
- *
1744
- ***/
1745
- 'advance': function() {
1746
- var args = collectDateArguments(arguments, true);
1747
- return updateDate(this, args[0], args[1], 1);
1748
- },
1749
-
1750
- /***
1751
- * @method rewind(<set>, [reset] = false)
1752
- * @returns Date
1753
- * @short Sets the date back.
1754
- * @extra This method can accept multiple formats including a single number as a timestamp, an object, or enumerated parameters (as with the Date constructor). If [reset] is %true%, any units more specific than those passed will be reset. For more see @date_format.
1755
- * @example
1756
- *
1757
- * new Date().rewind({ year: 2 }) -> 2 years in the past
1758
- * new Date().rewind(0, 2, 3) -> 2 months 3 days in the past
1759
- * new Date().rewind(86400000) -> 1 day in the past
1760
- *
1761
- ***/
1762
- 'rewind': function() {
1763
- var args = collectDateArguments(arguments, true);
1764
- return updateDate(this, args[0], args[1], -1);
1765
- },
1766
-
1767
- /***
1768
- * @method isValid()
1769
- * @returns Boolean
1770
- * @short Returns true if the date is valid.
1771
- * @example
1772
- *
1773
- * new Date().isValid() -> true
1774
- * new Date('flexor').isValid() -> false
1775
- *
1776
- ***/
1777
- 'isValid': function() {
1778
- return !isNaN(this.getTime());
1779
- },
1780
-
1781
- /***
1782
- * @method isAfter(<d>, [margin] = 0)
1783
- * @returns Boolean
1784
- * @short Returns true if the date is after the <d>.
1785
- * @extra [margin] is to allow extra margin of error (in ms). <d> will accept a date object, timestamp, or text format. If not specified, <d> is assumed to be now. See @date_format for more.
1786
- * @example
1787
- *
1788
- * new Date().isAfter('tomorrow') -> false
1789
- * new Date().isAfter('yesterday') -> true
1790
- *
1791
- ***/
1792
- 'isAfter': function(d, margin, utc) {
1793
- return this.getTime() > date.create(d).getTime() - (margin || 0);
1794
- },
1795
-
1796
- /***
1797
- * @method isBefore(<d>, [margin] = 0)
1798
- * @returns Boolean
1799
- * @short Returns true if the date is before <d>.
1800
- * @extra [margin] is to allow extra margin of error (in ms). <d> will accept a date object, timestamp, or text format. If not specified, <d> is assumed to be now. See @date_format for more.
1801
- * @example
1802
- *
1803
- * new Date().isBefore('tomorrow') -> true
1804
- * new Date().isBefore('yesterday') -> false
1805
- *
1806
- ***/
1807
- 'isBefore': function(d, margin) {
1808
- return this.getTime() < date.create(d).getTime() + (margin || 0);
1809
- },
1810
-
1811
- /***
1812
- * @method isBetween(<d1>, <d2>, [margin] = 0)
1813
- * @returns Boolean
1814
- * @short Returns true if the date falls between <d1> and <d2>.
1815
- * @extra [margin] is to allow extra margin of error (in ms). <d1> and <d2> will accept a date object, timestamp, or text format. If not specified, they are assumed to be now. See @date_format for more.
1816
- * @example
1817
- *
1818
- * new Date().isBetween('yesterday', 'tomorrow') -> true
1819
- * new Date().isBetween('last year', '2 years ago') -> false
1820
- *
1821
- ***/
1822
- 'isBetween': function(d1, d2, margin) {
1823
- var t = this.getTime();
1824
- var t1 = date.create(d1).getTime();
1825
- var t2 = date.create(d2).getTime();
1826
- var lo = math.min(t1, t2);
1827
- var hi = math.max(t1, t2);
1828
- margin = margin || 0;
1829
- return (lo - margin < t) && (hi + margin > t);
1830
- },
1831
-
1832
- /***
1833
- * @method isLeapYear()
1834
- * @returns Boolean
1835
- * @short Returns true if the date is a leap year.
1836
- * @example
1837
- *
1838
- * Date.create('2000').isLeapYear() -> true
1839
- *
1840
- ***/
1841
- 'isLeapYear': function() {
1842
- var year = callDateGet(this, 'FullYear');
1843
- return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
1844
- },
1845
-
1846
- /***
1847
- * @method daysInMonth()
1848
- * @returns Number
1849
- * @short Returns the number of days in the date's month.
1850
- * @example
1851
- *
1852
- * Date.create('May').daysInMonth() -> 31
1853
- * Date.create('February, 2000').daysInMonth() -> 29
1854
- *
1855
- ***/
1856
- 'daysInMonth': function() {
1857
- return 32 - callDateGet(new date(callDateGet(this, 'FullYear'), callDateGet(this, 'Month'), 32), 'Date');
1858
- },
1859
-
1860
- /***
1861
- * @method format(<format>, [locale] = currentLocale)
1862
- * @returns String
1863
- * @short Formats and outputs the date.
1864
- * @extra <format> can be a number of pre-determined formats or a string of tokens. Locale-specific formats are %short%, %long%, and %full% which have their own aliases and can be called with %date.short()%, etc. If <format> is not specified the %long% format is assumed. [locale] specifies a locale code to use (if not specified the current locale is used). See @date_format for more details.
1865
- *
1866
- * @set
1867
- * short
1868
- * long
1869
- * full
1870
- *
1871
- * @example
1872
- *
1873
- * Date.create().format() -> ex. July 4, 2003
1874
- * Date.create().format('{Weekday} {d} {Month}, {yyyy}') -> ex. Monday July 4, 2003
1875
- * Date.create().format('{hh}:{mm}') -> ex. 15:57
1876
- * Date.create().format('{12hr}:{mm}{tt}') -> ex. 3:57pm
1877
- * Date.create().format(Date.ISO8601_DATETIME) -> ex. 2011-07-05 12:24:55.528Z
1878
- * Date.create('last week').format('short', 'ja') -> ex. 先週
1879
- * Date.create('yesterday').format(function(value,unit,ms,loc) {
1880
- * // value = 1, unit = 3, ms = -86400000, loc = [current locale object]
1881
- * }); -> ex. 1 day ago
1882
- *
1883
- ***/
1884
- 'format': function(f, localeCode) {
1885
- return formatDate(this, f, false, localeCode);
1886
- },
1887
-
1888
- /***
1889
- * @method relative([fn], [locale] = currentLocale)
1890
- * @returns String
1891
- * @short Returns a relative date string offset to the current time.
1892
- * @extra [fn] can be passed to provide for more granular control over the resulting string. [fn] is passed 4 arguments: the adjusted value, unit, offset in milliseconds, and a localization object. As an alternate syntax, [locale] can also be passed as the first (and only) parameter. For more, see @date_format.
1893
- * @example
1894
- *
1895
- * Date.create('90 seconds ago').relative() -> 1 minute ago
1896
- * Date.create('January').relative() -> ex. 5 months ago
1897
- * Date.create('January').relative('ja') -> 3ヶ月前
1898
- * Date.create('120 minutes ago').relative(function(val,unit,ms,loc) {
1899
- * // value = 2, unit = 3, ms = -7200, loc = [current locale object]
1900
- * }); -> ex. 5 months ago
1901
- *
1902
- ***/
1903
- 'relative': function(f, localeCode) {
1904
- if(isString(f)) {
1905
- localeCode = f;
1906
- f = null;
1907
- }
1908
- return formatDate(this, f, true, localeCode);
1909
- },
1910
-
1911
- /***
1912
- * @method is(<d>, [margin] = 0)
1913
- * @returns Boolean
1914
- * @short Returns true if the date is <d>.
1915
- * @extra <d> will accept a date object, timestamp, or text format. %is% additionally understands more generalized expressions like month/weekday names, 'today', etc, and compares to the precision implied in <d>. [margin] allows an extra margin of error in milliseconds. For more, see @date_format.
1916
- * @example
1917
- *
1918
- * Date.create().is('July') -> true or false?
1919
- * Date.create().is('1776') -> false
1920
- * Date.create().is('today') -> true
1921
- * Date.create().is('weekday') -> true or false?
1922
- * Date.create().is('July 4, 1776') -> false
1923
- * Date.create().is(-6106093200000) -> false
1924
- * Date.create().is(new Date(1776, 6, 4)) -> false
1925
- *
1926
- ***/
1927
- 'is': function(d, margin, utc) {
1928
- var tmp, comp;
1929
- if(!this.isValid()) return;
1930
- if(isString(d)) {
1931
- d = d.trim().toLowerCase();
1932
- comp = this.clone().utc(utc);
1933
- switch(true) {
1934
- case d === 'future': return this.getTime() > new date().getTime();
1935
- case d === 'past': return this.getTime() < new date().getTime();
1936
- case d === 'weekday': return callDateGet(comp, 'Day') > 0 && callDateGet(comp, 'Day') < 6;
1937
- case d === 'weekend': return callDateGet(comp, 'Day') === 0 || callDateGet(comp, 'Day') === 6;
1938
- case (tmp = English['weekdays'].indexOf(d) % 7) > -1: return callDateGet(comp, 'Day') === tmp;
1939
- case (tmp = English['months'].indexOf(d) % 12) > -1: return callDateGet(comp, 'Month') === tmp;
1940
- }
1941
- }
1942
- return compareDate(this, d, margin, utc);
1943
- },
1944
-
1945
- /***
1946
- * @method reset([unit] = 'hours')
1947
- * @returns Date
1948
- * @short Resets the unit passed and all smaller units. Default is "hours", effectively resetting the time.
1949
- * @example
1950
- *
1951
- * Date.create().reset('day') -> Beginning of today
1952
- * Date.create().reset('month') -> 1st of the month
1953
- *
1954
- ***/
1955
- 'reset': function(unit) {
1956
- var params = {}, recognized;
1957
- unit = unit || 'hours';
1958
- if(unit === 'date') unit = 'days';
1959
- recognized = DateUnits.some(function(u) {
1960
- return unit === u.unit || unit === u.unit + 's';
1961
- });
1962
- params[unit] = unit.match(/^days?/) ? 1 : 0;
1963
- return recognized ? this.set(params, true) : this;
1964
- },
1965
-
1966
- /***
1967
- * @method clone()
1968
- * @returns Date
1969
- * @short Clones the date.
1970
- * @example
1971
- *
1972
- * Date.create().clone() -> Copy of now
1973
- *
1974
- ***/
1975
- 'clone': function() {
1976
- var d = new date(this.getTime());
1977
- d.utc(this.isUTC());
1978
- return d;
1979
- }
1980
-
1981
- });
1982
-
1983
-
1984
- // Instance aliases
1985
- date.extend({
1986
-
1987
- /***
1988
- * @method iso()
1989
- * @alias toISOString
1990
- *
1991
- ***/
1992
- 'iso': function() {
1993
- return this.toISOString();
1994
- },
1995
-
1996
- /***
1997
- * @method getWeekday()
1998
- * @returns Number
1999
- * @short Alias for %getDay%.
2000
- * @set
2001
- * getUTCWeekday
2002
- *
2003
- * @example
2004
- *
2005
- + Date.create().getWeekday(); -> (ex.) 3
2006
- + Date.create().getUTCWeekday(); -> (ex.) 3
2007
- *
2008
- ***/
2009
- 'getWeekday': date.prototype.getDay,
2010
- 'getUTCWeekday': date.prototype.getUTCDay
2011
-
2012
- });
2013
-
2014
-
2015
-
2016
- /***
2017
- * Number module
2018
- *
2019
- ***/
2020
-
2021
- /***
2022
- * @method [unit]()
2023
- * @returns Number
2024
- * @short Takes the number as a corresponding unit of time and converts to milliseconds.
2025
- * @extra Method names can be both singular and plural. Note that as "a month" is ambiguous as a unit of time, %months% will be equivalent to 30.4375 days, the average number in a month. Be careful using %months% if you need exact precision.
2026
- *
2027
- * @set
2028
- * millisecond
2029
- * milliseconds
2030
- * second
2031
- * seconds
2032
- * minute
2033
- * minutes
2034
- * hour
2035
- * hours
2036
- * day
2037
- * days
2038
- * week
2039
- * weeks
2040
- * month
2041
- * months
2042
- * year
2043
- * years
2044
- *
2045
- * @example
2046
- *
2047
- * (5).milliseconds() -> 5
2048
- * (10).hours() -> 36000000
2049
- * (1).day() -> 86400000
2050
- *
2051
- ***
2052
- * @method [unit]Before([d], [locale] = currentLocale)
2053
- * @returns Date
2054
- * @short Returns a date that is <n> units before [d], where <n> is the number.
2055
- * @extra [d] will accept a date object, timestamp, or text format. Note that "months" is ambiguous as a unit of time. If the target date falls on a day that does not exist (ie. August 31 -> February 31), the date will be shifted to the last day of the month. Be careful using %monthsBefore% if you need exact precision. See @date_format for more.
2056
- *
2057
- * @set
2058
- * millisecondBefore
2059
- * millisecondsBefore
2060
- * secondBefore
2061
- * secondsBefore
2062
- * minuteBefore
2063
- * minutesBefore
2064
- * hourBefore
2065
- * hoursBefore
2066
- * dayBefore
2067
- * daysBefore
2068
- * weekBefore
2069
- * weeksBefore
2070
- * monthBefore
2071
- * monthsBefore
2072
- * yearBefore
2073
- * yearsBefore
2074
- *
2075
- * @example
2076
- *
2077
- * (5).daysBefore('tuesday') -> 5 days before tuesday of this week
2078
- * (1).yearBefore('January 23, 1997') -> January 23, 1996
2079
- *
2080
- ***
2081
- * @method [unit]Ago()
2082
- * @returns Date
2083
- * @short Returns a date that is <n> units ago.
2084
- * @extra Note that "months" is ambiguous as a unit of time. If the target date falls on a day that does not exist (ie. August 31 -> February 31), the date will be shifted to the last day of the month. Be careful using %monthsAgo% if you need exact precision.
2085
- *
2086
- * @set
2087
- * millisecondAgo
2088
- * millisecondsAgo
2089
- * secondAgo
2090
- * secondsAgo
2091
- * minuteAgo
2092
- * minutesAgo
2093
- * hourAgo
2094
- * hoursAgo
2095
- * dayAgo
2096
- * daysAgo
2097
- * weekAgo
2098
- * weeksAgo
2099
- * monthAgo
2100
- * monthsAgo
2101
- * yearAgo
2102
- * yearsAgo
2103
- *
2104
- * @example
2105
- *
2106
- * (5).weeksAgo() -> 5 weeks ago
2107
- * (1).yearAgo() -> January 23, 1996
2108
- *
2109
- ***
2110
- * @method [unit]After([d], [locale] = currentLocale)
2111
- * @returns Date
2112
- * @short Returns a date <n> units after [d], where <n> is the number.
2113
- * @extra [d] will accept a date object, timestamp, or text format. Note that "months" is ambiguous as a unit of time. If the target date falls on a day that does not exist (ie. August 31 -> February 31), the date will be shifted to the last day of the month. Be careful using %monthsAfter% if you need exact precision. See @date_format for more.
2114
- *
2115
- * @set
2116
- * millisecondAfter
2117
- * millisecondsAfter
2118
- * secondAfter
2119
- * secondsAfter
2120
- * minuteAfter
2121
- * minutesAfter
2122
- * hourAfter
2123
- * hoursAfter
2124
- * dayAfter
2125
- * daysAfter
2126
- * weekAfter
2127
- * weeksAfter
2128
- * monthAfter
2129
- * monthsAfter
2130
- * yearAfter
2131
- * yearsAfter
2132
- *
2133
- * @example
2134
- *
2135
- * (5).daysAfter('tuesday') -> 5 days after tuesday of this week
2136
- * (1).yearAfter('January 23, 1997') -> January 23, 1998
2137
- *
2138
- ***
2139
- * @method [unit]FromNow()
2140
- * @returns Date
2141
- * @short Returns a date <n> units from now.
2142
- * @extra Note that "months" is ambiguous as a unit of time. If the target date falls on a day that does not exist (ie. August 31 -> February 31), the date will be shifted to the last day of the month. Be careful using %monthsFromNow% if you need exact precision.
2143
- *
2144
- * @set
2145
- * millisecondFromNow
2146
- * millisecondsFromNow
2147
- * secondFromNow
2148
- * secondsFromNow
2149
- * minuteFromNow
2150
- * minutesFromNow
2151
- * hourFromNow
2152
- * hoursFromNow
2153
- * dayFromNow
2154
- * daysFromNow
2155
- * weekFromNow
2156
- * weeksFromNow
2157
- * monthFromNow
2158
- * monthsFromNow
2159
- * yearFromNow
2160
- * yearsFromNow
2161
- *
2162
- * @example
2163
- *
2164
- * (5).weeksFromNow() -> 5 weeks ago
2165
- * (1).yearFromNow() -> January 23, 1998
2166
- *
2167
- ***/
2168
- function buildNumberToDateAlias(u, multiplier) {
2169
- var unit = u.unit, methods = {};
2170
- function base() { return round(this * multiplier); }
2171
- function after() { return createDate(arguments)[u.addMethod](this); }
2172
- function before() { return createDate(arguments)[u.addMethod](-this); }
2173
- methods[unit] = base;
2174
- methods[unit + 's'] = base;
2175
- methods[unit + 'Before'] = before;
2176
- methods[unit + 'sBefore'] = before;
2177
- methods[unit + 'Ago'] = before;
2178
- methods[unit + 'sAgo'] = before;
2179
- methods[unit + 'After'] = after;
2180
- methods[unit + 'sAfter'] = after;
2181
- methods[unit + 'FromNow'] = after;
2182
- methods[unit + 'sFromNow'] = after;
2183
- number.extend(methods);
2184
- }
2185
-
2186
- number.extend({
2187
-
2188
- /***
2189
- * @method duration([locale] = currentLocale)
2190
- * @returns String
2191
- * @short Takes the number as milliseconds and returns a unit-adjusted localized string.
2192
- * @extra This method is the same as %Date#relative% without the localized equivalent of "from now" or "ago". [locale] can be passed as the first (and only) parameter. Note that this method is only available when the dates package is included.
2193
- * @example
2194
- *
2195
- * (500).duration() -> '500 milliseconds'
2196
- * (1200).duration() -> '1 second'
2197
- * (75).minutes().duration() -> '1 hour'
2198
- * (75).minutes().duration('es') -> '1 hora'
2199
- *
2200
- ***/
2201
- 'duration': function(localeCode) {
2202
- return getLocalization(localeCode).getDuration(this);
2203
- }
2204
-
2205
- });
2206
-
2207
-
2208
- English = CurrentLocalization = date.addLocale('en', {
2209
- 'plural': true,
2210
- 'timeMarker': 'at',
2211
- 'ampm': 'am,pm',
2212
- 'months': 'January,February,March,April,May,June,July,August,September,October,November,December',
2213
- 'weekdays': 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday',
2214
- 'units': 'millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s',
2215
- 'numbers': 'one,two,three,four,five,six,seven,eight,nine,ten',
2216
- 'articles': 'a,an,the',
2217
- 'tokens': 'the,st|nd|rd|th,of',
2218
- 'short': '{Month} {d}, {yyyy}',
2219
- 'long': '{Month} {d}, {yyyy} {h}:{mm}{tt}',
2220
- 'full': '{Weekday} {Month} {d}, {yyyy} {h}:{mm}:{ss}{tt}',
2221
- 'past': '{num} {unit} {sign}',
2222
- 'future': '{num} {unit} {sign}',
2223
- 'duration': '{num} {unit}',
2224
- 'modifiers': [
2225
- { 'name': 'day', 'src': 'yesterday', 'value': -1 },
2226
- { 'name': 'day', 'src': 'today', 'value': 0 },
2227
- { 'name': 'day', 'src': 'tomorrow', 'value': 1 },
2228
- { 'name': 'sign', 'src': 'ago|before', 'value': -1 },
2229
- { 'name': 'sign', 'src': 'from now|after|from|in|later', 'value': 1 },
2230
- { 'name': 'edge', 'src': 'last day', 'value': -2 },
2231
- { 'name': 'edge', 'src': 'end', 'value': -1 },
2232
- { 'name': 'edge', 'src': 'first day|beginning', 'value': 1 },
2233
- { 'name': 'shift', 'src': 'last', 'value': -1 },
2234
- { 'name': 'shift', 'src': 'the|this', 'value': 0 },
2235
- { 'name': 'shift', 'src': 'next', 'value': 1 }
2236
- ],
2237
- 'dateParse': [
2238
- '{num} {unit} {sign}',
2239
- '{sign} {num} {unit}',
2240
- '{month} {year}',
2241
- '{shift} {unit=5-7}',
2242
- '{0?} {date}{1}',
2243
- '{0?} {edge} of {shift?} {unit=4-7?}{month?}{year?}'
2244
- ],
2245
- 'timeParse': [
2246
- '{0} {num}{1} {day} of {month} {year?}',
2247
- '{weekday?} {month} {date}{1?} {year?}',
2248
- '{date} {month} {year}',
2249
- '{date} {month}',
2250
- '{shift} {weekday}',
2251
- '{shift} week {weekday}',
2252
- '{weekday} {2?} {shift} week',
2253
- '{num} {unit=4-5} {sign} {day}',
2254
- '{0?} {date}{1} of {month}',
2255
- '{0?}{month?} {date?}{1?} of {shift} {unit=6-7}'
2256
- ]
2257
- });
2258
-
2259
- buildDateUnits();
2260
- buildDateMethods();
2261
- buildCoreInputFormats();
2262
- buildDateOutputShortcuts();
2263
- buildAsianDigits();
2264
- buildRelativeAliases();
2265
- buildUTCAliases();
2266
- setDateProperties();
2267
-