sugar-rails 1.2.5 → 1.2.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,2210 @@
1
+ // Google Closure Compiler will output a wrapping function here.
2
+ (function() {
3
+
4
+ // A few optimizations for Google Closure Compiler will save us a couple kb in the release script.
5
+ var regexp = RegExp, object = Object, date = Date, number = Number, Undefined, English;
6
+
7
+ function isDefined(o) {
8
+ return o !== Undefined;
9
+ }
10
+
11
+ function isUndefined(o) {
12
+ return o === Undefined;
13
+ }
14
+
15
+
16
+ /***
17
+ * Date module
18
+ *
19
+ ***/
20
+
21
+ var TimeFormat = ['hour','minute','second','meridian','utc','offset_sign','offset_hours','offset_minutes']
22
+ var FloatReg = '\\d{1,2}(?:[,.]\\d+)?';
23
+ var RequiredTime = '('+FloatReg+'):?('+FloatReg+')?:?('+FloatReg+')?(am|pm)?(?:(Z)|(?:([+-])(\\d{2})(?::?(\\d{2}))?)?)?';
24
+ var OptionalTime = '\\s*(?:(?:t|at |\\s+)' + RequiredTime + ')?';
25
+
26
+ var LowerAsianDigits = '一二三四五六七八九';
27
+ var UpperAsianDigits = '十百千万';
28
+ var AsianDigitReg = regexp('[' + LowerAsianDigits + UpperAsianDigits + ']', 'g');
29
+ var DateInputFormats = [];
30
+ var DateArgumentUnits;
31
+ var DateUnitsReversed;
32
+
33
+ var StaticInputFormats = [
34
+ // @date_format 2010
35
+ { src: '(\\d{4})', to: ['year'] },
36
+ // @date_format 2010-05
37
+ // @date_format 2010.05
38
+ // @date_format 2010/05
39
+ // @date_format 2010-05-25 (ISO8601)
40
+ // @date_format 2010-05-25T12:30:40.299Z (ISO8601)
41
+ // @date_format 2010-05-25T12:30:40.299+01:00 (ISO8601)
42
+ // @date_format 2010.05.25
43
+ // @date_format 2010/05/25
44
+ { src: '([+-])?(\\d{4})[-.]?({month})[-.]?(\\d{1,2})?', to: ['year_sign','year','month','date'] },
45
+ // @date_format 05-25
46
+ // @date_format 05/25
47
+ // @date_format 05.25
48
+ // @date_format 05-25-2010
49
+ // @date_format 05/25/2010
50
+ // @date_format 05.25.2010
51
+ { src: '(\\d{1,2})[-.\\/]({month})[-.\\/]?(\\d{2,4})?', to: ['month','date','year'], variant: true },
52
+ // @date_format Date(628318530718)
53
+ { src: '\\/Date\\((\\d+(?:\\+\\d{4})?)\\)\\/', to: ['timestamp'], time: false }
54
+ ];
55
+
56
+ var DateOutputFormats = [
57
+ {
58
+ token: 'f{1,4}|ms|milliseconds',
59
+ format: function(d) {
60
+ return d.getMilliseconds();
61
+ }
62
+ },
63
+ {
64
+ token: 'ss?|seconds',
65
+ format: function(d, len) {
66
+ return d.getSeconds();
67
+ }
68
+ },
69
+ {
70
+ token: 'mm?|minutes',
71
+ format: function(d, len) {
72
+ return d.getMinutes();
73
+ }
74
+ },
75
+ {
76
+ token: 'hh?|hours|12hr',
77
+ format: function(d) {
78
+ return getShortHour(d);
79
+ }
80
+ },
81
+ {
82
+ token: 'HH?|24hr',
83
+ format: function(d) {
84
+ return d.getHours();
85
+ }
86
+ },
87
+ {
88
+ token: 'dd?|date|day',
89
+ format: function(d) {
90
+ return d.getDate();
91
+ }
92
+ },
93
+ {
94
+ token: 'dow|weekday',
95
+ word: true,
96
+ format: function(d, loc, n, t) {
97
+ return loc['weekdays'][d.getDay() + (n - 1) * 7];
98
+ }
99
+ },
100
+ {
101
+ token: 'MM?',
102
+ format: function(d) {
103
+ return d.getMonth() + 1;
104
+ }
105
+ },
106
+ {
107
+ token: 'mon|month',
108
+ word: true,
109
+ format: function(d, loc, n, len) {
110
+ return loc['months'][d.getMonth() + (n - 1) * 12];
111
+ }
112
+ },
113
+ {
114
+ token: 'y{2,4}|year',
115
+ format: function(d) {
116
+ return d.getFullYear();
117
+ }
118
+ },
119
+ {
120
+ token: '[Tt]{1,2}',
121
+ format: function(d, loc, n, format) {
122
+ var m = getMeridian(d);
123
+ if(format.length === 1) m = m.first();
124
+ if(format.first() === 'T') m = m.toUpperCase();
125
+ return m;
126
+ }
127
+ },
128
+ {
129
+ token: 'z{1,4}|tz|timezone',
130
+ text: true,
131
+ format: function(d, loc, n, format) {
132
+ var tz = d.getUTCOffset();
133
+ if(format == 'z' || format == 'zz') {
134
+ tz = tz.replace(/(\d{2})(\d{2})/, function(f,h,m) {
135
+ return h.toNumber().pad(format.length);
136
+ });
137
+ }
138
+ return tz;
139
+ }
140
+ },
141
+ {
142
+ token: 'iso(tz|timezone)',
143
+ format: function(d) {
144
+ return d.getUTCOffset(true);
145
+ }
146
+ },
147
+ {
148
+ token: 'ord',
149
+ format: function(d) {
150
+ return d.getDate().ordinalize();
151
+ }
152
+ }
153
+ ];
154
+
155
+ var DateUnits = [
156
+ {
157
+ unit: 'year',
158
+ method: 'FullYear',
159
+ multiplier: function(d) {
160
+ var adjust = d ? (d.isLeapYear() ? 1 : 0) : 0.25;
161
+ return (365 + adjust) * 24 * 60 * 60 * 1000;
162
+ }
163
+ },
164
+ {
165
+ unit: 'month',
166
+ method: 'Month',
167
+ multiplier: function(d, ms) {
168
+ var days = 30.4375, inMonth;
169
+ if(d) {
170
+ inMonth = d.daysInMonth();
171
+ if(ms <= inMonth.days()) {
172
+ days = inMonth;
173
+ }
174
+ }
175
+ return days * 24 * 60 * 60 * 1000;
176
+ }
177
+ },
178
+ {
179
+ unit: 'week',
180
+ method: 'Week',
181
+ multiplier: function() {
182
+ return 7 * 24 * 60 * 60 * 1000;
183
+ }
184
+ },
185
+ {
186
+ unit: 'day',
187
+ method: 'Date',
188
+ multiplier: function() {
189
+ return 24 * 60 * 60 * 1000;
190
+ }
191
+ },
192
+ {
193
+ unit: 'hour',
194
+ method: 'Hours',
195
+ multiplier: function() {
196
+ return 60 * 60 * 1000;
197
+ }
198
+ },
199
+ {
200
+ unit: 'minute',
201
+ method: 'Minutes',
202
+ multiplier: function() {
203
+ return 60 * 1000;
204
+ }
205
+ },
206
+ {
207
+ unit: 'second',
208
+ method: 'Seconds',
209
+ multiplier: function() {
210
+ return 1000;
211
+ }
212
+ },
213
+ {
214
+ unit: 'millisecond',
215
+ method: 'Milliseconds',
216
+ multiplier: function() {
217
+ return 1;
218
+ }
219
+ }
220
+ ];
221
+
222
+
223
+
224
+
225
+ // Date Localization
226
+
227
+ var Localizations = {};
228
+
229
+ var CommonLocales = {
230
+
231
+ 'en': '2;;January,February,March,April,May,June,July,August,September,October,November,December;Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday;millisecond:|s,second:|s,minute:|s,hour:|s,day:|s,week:|s,month:|s,year:|s;one,two,three,four,five,six,seven,eight,nine,ten;a,an,the;the,st|nd|rd|th,of;{num} {unit} {sign},{num} {unit=4-5} {sign} {day},{weekday?} {month} {date}{1} {year?} {time?},{date} {month} {year},{month} {year},{shift?} {weekday} {time?},{shift} week {weekday} {time?},{shift} {unit=5-7},{0} {edge} of {shift?} {unit=4-7?}{month?}{year?},{weekday} {2} {shift} week,{0} {date}{1} of {month},{0}{month?} {date?}{1} of {shift} {unit=6-7},{day} at {time?},{time} {day};{Month} {d}, {yyyy};,yesterday,today,tomorrow;,ago|before,,from now|after|from;,last,the|this,next;last day,end,,first day|beginning',
232
+
233
+ 'ja': '1;月;;日曜日,月曜日,火曜日,水曜日,木曜日,金曜日,土曜日;ミリ秒,秒,分,時間,日,週間|週,ヶ月|ヵ月|月,年;;;;{num}{unit}{sign},{shift}{unit=5-7}{weekday?},{year}年{month?}月?{date?}日?,{month}月{date?}日?,{date}日;{yyyy}年{M}月{d}日;一昨日,昨日,今日,明日,明後日;,前,,後;,去|先,,来',
234
+
235
+ 'ko': '1;월;;일요일,월요일,화요일,수요일,목요일,금요일,토요일;밀리초,초,분,시간,일,주,개월|달,년;일|한,이,삼,사,오,육,칠,팔,구,십;;;{num}{unit} {sign},{shift} {unit=5-7},{shift} {unit=5?} {weekday},{year}년{month?}월?{date?}일?,{month}월{date?}일?,{date}일;{yyyy}년{M}월{d}일;그저께,어제,오늘,내일,모레;,전,,후;,지난|작,이번,다음|내',
236
+
237
+ 'ru': '4;;Январ:я|ь,Феврал:я|ь,Март:а|,Апрел:я|ь,Ма:я|й,Июн:я|ь,Июл:я|ь,Август:а|,Сентябр:я|ь,Октябр:я|ь,Ноябр:я|ь,Декабр:я|ь;Воскресенье,Понедельник,Вторник,Среда,Четверг,Пятница,Суббота;миллисекунд:а|у|ы|,секунд:а|у|ы|,минут:а|у|ы|,час:||а|ов,день|день|дня|дней,недел:я|ю|и|ь|е,месяц:||а|ев|е,год|год|года|лет|году;од:ин|ну,дв:а|е,три,четыре,пять,шесть,семь,восемь,девять,десять;;в|на,года;{num} {unit} {sign},{sign} {num} {unit},{date} {month} {year?} {1},{month} {year},{0} {shift} {unit=5-7};{d} {month} {yyyy} года;позавчера,вчера,сегодня,завтра,послезавтра;,назад,,через;,прошло:й|м,,следующе:й|м',
238
+
239
+ 'es': '6;;enero,febrero,marzo,abril,mayo,junio,julio,agosto,septiembre,octubre,noviembre,diciembre;domingo,lunes,martes,miércoles|miercoles,jueves,viernes,sábado|sabado;milisegundo:|s,segundo:|s,minuto:|s,hora:|s,día|días|dia|dias,semana:|s,mes:|es,año|años|ano|anos;uno,dos,tres,cuatro,cinco,seis,siete,ocho,nueve,diez;;el,de;{sign} {num} {unit},{num} {unit} {sign},{date?} {1} {month} {1} {year?},{0} {unit=5-7} {shift},{0} {shift} {unit=5-7};{d} de {month} de {yyyy};anteayer,ayer,hoy,mañana|manana;,hace,,de ahora;,pasad:o|a,,próximo|próxima|proximo|proxima',
240
+
241
+ 'pt': '6;;janeiro,fevereiro,março,abril,maio,junho,julho,agosto,setembro,outubro,novembro,dezembro;domingo,segunda-feira,terça-feira,quarta-feira,quinta-feira,sexta-feira,sábado|sabado;milisegundo:|s,segundo:|s,minuto:|s,hora:|s,dia:|s,semana:|s,mês|mêses|mes|meses,ano:|s;um,dois,três|tres,quatro,cinco,seis,sete,oito,nove,dez,uma,duas;;a,de;{num} {unit} {sign},{sign} {num} {unit},{date?} {1} {month} {1} {year?},{0} {unit=5-7} {shift},{0} {shift} {unit=5-7};{d} de {month} de {yyyy};anteontem,ontem,hoje,amanh:ã|a;,atrás|atras|há|ha,,daqui a;,passad:o|a,,próximo|próxima|proximo|proxima',
242
+
243
+ 'fr': '2;;janvier,février|fevrier,mars,avril,mai,juin,juillet,août,septembre,octobre,novembre,décembre|decembre;dimanche,lundi,mardi,mercredi,jeudi,vendredi,samedi;milliseconde:|s,seconde:|s,minute:|s,heure:|s,jour:|s,semaine:|s,mois,an:|s|née|nee;un:|e,deux,trois,quatre,cinq,six,sept,huit,neuf,dix;;l\'|la|le;{sign} {num} {unit},{sign} {num} {unit},{0} {date?} {month} {year?},{0} {unit=5-7} {shift};{d} {month} {yyyy};,hier,aujourd\'hui,demain;,il y a,,dans|d\'ici;,derni:er|ère|ere,,prochain:|e',
244
+
245
+ 'it': '2;;Gennaio,Febbraio,Marzo,Aprile,Maggio,Giugno,Luglio,Agosto,Settembre,Ottobre,Novembre,Dicembre;Domenica,Luned:ì|i,Marted:ì|i,Mercoled:ì|i,Gioved:ì|i,Venerd:ì|i,Sabato;millisecond:o|i,second:o|i,minut:o|i,or:a|e,giorn:o|i,settiman:a|e,mes:e|i,ann:o|i;un:|\'|a|o,due,tre,quattro,cinque,sei,sette,otto,nove,dieci;;l\'|la|il;{num} {unit} {sign},{weekday?} {date?} {month} {year?},{0} {unit=5-7} {shift},{0} {shift} {unit=5-7};{d} {month} {yyyy};,ieri,oggi,domani,dopodomani;,fa,,da adesso;,scors:o|a,,prossim:o|a',
246
+
247
+ 'de': '2;;Januar,Februar,März|Marz,April,Mai,Juni,Juli,August,September,Oktober,November,Dezember;Sonntag,Montag,Dienstag,Mittwoch,Donnerstag,Freitag,Samstag;Millisekunde:|n,Sekunde:|n,Minute:|n,Stunde:|n,Tag:|en,Woche:|n,Monat:|en,Jahr:|en;ein:|e|er|em|en,zwei,drei,vier,fuenf,sechs,sieben,acht,neun,zehn;;der;{sign} {num} {unit},{num} {unit} {sign},{num} {unit} {sign},{sign} {num} {unit},{weekday?} {date?} {month} {year?},{shift} {unit=5-7};{d}. {Month} {yyyy};vorgestern,gestern,heute,morgen,übermorgen|ubermorgen|uebermorgen;,vor:|her,,in;,letzte:|r|n|s,,nächste:|r|n|s+naechste:|r|n|s',
248
+
249
+ 'zh-TW': '1;月;;日,一,二,三,四,五,六;毫秒,秒鐘,分鐘,小時,天,個星期|週,個月,年;;;日|號;{num}{unit}{sign},星期{weekday},{shift}{unit=5-7},{shift}{unit=5}{weekday},{year}年{month?}月?{date?}{0},{month}月{date?}{0},{date}{0};{yyyy}年{M}月{d}日;前天,昨天,今天,明天,後天;,前,,後;,上|去,這,下|明',
250
+
251
+ 'zh-CN': '1;月;;日,一,二,三,四,五,六;毫秒,秒钟,分钟,小时,天,个星期|周,个月,年;;;日|号;{num}{unit}{sign},星期{weekday},{shift}{unit=5-7},{shift}{unit=5}{weekday},{year}年{month?}月?{date?}{0},{month}月{date?}{0},{date}{0};{yyyy}年{M}月{d}日;前天,昨天,今天,明天,后天;,前,,后;,上|去,这,下|明'
252
+
253
+ }
254
+
255
+ function checkLocaleFormatsAdded(loc) {
256
+ var code = loc['code'];
257
+ if(loc.formatsAdded) return;
258
+ addDateInputFormat('(' + loc['months'].compact().join('|') + ')', ['month'], code);
259
+ addDateInputFormat('(' + loc['weekdays'].compact().join('|') + ')', ['weekday'], code);
260
+ addDateInputFormat('(' + loc['modifiers'].filter(function(m){ return m.name === 'day'; }).map('src').join('|') + ')', ['day'], code);
261
+ loc['formats'].each(function(src) {
262
+ loc.addFormat(src, code, false);
263
+ });
264
+ loc.formatsAdded = true;
265
+ }
266
+
267
+ function addDateInputFormat(format, match, locale, variant, method) {
268
+ method = method || 'push';
269
+ DateInputFormats[method]({
270
+ variant: variant,
271
+ locale: locale,
272
+ reg: regexp('^' + format + '$', 'i'),
273
+ to: match
274
+ });
275
+ }
276
+
277
+ function getLocalization(code, fallback, set) {
278
+ if(fallback && (!object.isString(code) || !code)) code = Date['currentLocale'];
279
+ if(code && !Localizations[code] || set) initializeLocalization(code, set);
280
+ return Localizations[code];
281
+ }
282
+
283
+ function initializeLocalization(code, set) {
284
+ set = set || getCommonLocalization(code);
285
+ if(!set) {
286
+ throw new Error('Invalid locale.');
287
+ }
288
+
289
+ function eachAlternate(str, fn) {
290
+ str = str.split('+').map(function(split) {
291
+ return split.replace(/(.+):(.+)$/, function(full, base, suffixes) {
292
+ return suffixes.split('|').map(function(suffix) {
293
+ return base + suffix;
294
+ }).join('|');
295
+ });
296
+ }).join('|');
297
+ return str.split('|').each(fn);
298
+ }
299
+
300
+ function setArray(name, abbreviate, multiple) {
301
+ var arr = [];
302
+ if(!set[name]) return;
303
+ set[name].forEach(function(el, i) {
304
+ eachAlternate(el, function(str, j) {
305
+ arr[j * multiple + i] = str.toLowerCase();
306
+ });
307
+ });
308
+ if(abbreviate) arr = arr.concat(set[name].map(function(str) {
309
+ return str.slice(0,3).toLowerCase();
310
+ }));
311
+ return set[name] = arr;
312
+ }
313
+
314
+ function getDigit(start, stop) {
315
+ var str = '[0-90-9]' + (start ? '{' + start + ',' + stop + '}' : '+');
316
+ if(set['digits']) str += '|[' + set['digits'] + ']+';
317
+ return str;
318
+ }
319
+
320
+ function getNum() {
321
+ var arr = [getDigit()].concat(set['articles']);
322
+ if(!set['digits']) arr = arr.concat(set['numbers']);
323
+ return arr.compact().join('|');
324
+ }
325
+
326
+ function setModifiers() {
327
+ var arr = [];
328
+ set.modifiersByName = {};
329
+ set['modifiers'].each(function(modifier) {
330
+ eachAlternate(modifier.src, function(t) {
331
+ set.modifiersByName[t] = modifier;
332
+ arr.push({ name: modifier.name, src: t, value: modifier.value });
333
+ });
334
+ });
335
+ arr.groupBy('name', function(name, group) {
336
+ group = group.map('src');
337
+ if(name === 'day') group = group.concat(set['weekdays']);
338
+ set[name] = group.join('|');
339
+ });
340
+ set['modifiers'] = arr;
341
+ }
342
+
343
+ setArray('months', true, 12);
344
+ setArray('weekdays', true, 7);
345
+ setArray('units', false, 8);
346
+ setArray('numbers', false, 10);
347
+
348
+ set['code'] = code;
349
+ set['date'] = getDigit(1,2);
350
+ set['year'] = getDigit(4,4);
351
+ set['num'] = getNum();
352
+
353
+ setModifiers();
354
+
355
+ if(set['monthSuffix']) {
356
+ set['month'] = getDigit(1,2);
357
+ set['months'] = (1).upto(12).map(function(n) { return n + set['monthSuffix']; });
358
+ }
359
+ Localizations[code] = new Localization(set);
360
+ }
361
+
362
+ function getCommonLocalization(code) {
363
+ if(code.slice(0,3) == 'en-') code = 'en';
364
+ if(!CommonLocales[code]) return null;
365
+ var set = { 'modifiers': [] }, pre = CommonLocales[code].split(';');
366
+ function bool(n) {
367
+ return !!(pre[0] & Math.pow(2,n-1));
368
+ }
369
+ ['months','weekdays','units','numbers','articles','optionals','formats'].each(function(name, i) {
370
+ set[name] = pre[i + 2] ? pre[i + 2].split(',') : [];
371
+ });
372
+ set['outputFormat'] = pre[9];
373
+ ['day','sign','shift','edge'].each(function(name, i) {
374
+ if(!pre[i + 10]) return;
375
+ pre[i + 10].split(',').each(function(t, j) {
376
+ if(t) set['modifiers'].push({ name: name, src: t, value: j - 2 });
377
+ });
378
+ });
379
+ if(bool(1)) {
380
+ set['digits'] = LowerAsianDigits + UpperAsianDigits;
381
+ if(set['numbers'].length > 0) {
382
+ set['digits'] += set['numbers'].join('');
383
+ } else {
384
+ set['numbers'] = LowerAsianDigits.split('');
385
+ }
386
+ set['monthSuffix'] = pre[1];
387
+ }
388
+ set['capitalizeUnit'] = (code == 'de');
389
+ set['hasPlural'] = bool(2);
390
+ set['pastRelativeFormat'] = set['formats'][0];
391
+ set['futureRelativeFormat'] = set['formats'][bool(3) ? 1 : 0];
392
+ set['durationFormat'] = set['formats'][0].replace(/\s*\{sign\}\s*/, '');
393
+ return set;
394
+ }
395
+
396
+ function getVariant(locale) {
397
+ if(!locale) locale = Date['currentLocale'];
398
+ return locale != 'en' && locale != 'en-US';
399
+ }
400
+
401
+ function Localization(l) {
402
+ object.merge(this, l);
403
+ }
404
+
405
+ object.merge(Localization.prototype, {
406
+
407
+ getMonth: function(n) {
408
+ if(object.isNumber(n)) {
409
+ return n - 1;
410
+ } else {
411
+ return this['months'].findIndex(regexp(n, 'i')) % 12;
412
+ }
413
+ },
414
+
415
+ getWeekday: function(n) {
416
+ return this['weekdays'].findIndex(regexp(n, 'i')) % 7;
417
+ },
418
+
419
+ getNumber: function(n) {
420
+ var i;
421
+ if(object.isNumber(n)) {
422
+ return n;
423
+ } else if(n && (i = this['numbers'].indexOf(n)) !== -1) {
424
+ return (i + 1) % 10;
425
+ } else {
426
+ return 1;
427
+ }
428
+ },
429
+
430
+ getNumericDate: function(n) {
431
+ var self = this;
432
+ return n.replace(this['numbers'][9], '').each(function(d) {
433
+ return self.getNumber(d);
434
+ }).join('');
435
+ },
436
+
437
+ getEnglishUnit: function(n) {
438
+ return English['units'][this['units'].indexOf(n) % 8];
439
+ },
440
+
441
+ relative: function(adu) {
442
+ return this.convertAdjustedToFormat(adu, adu[2] > 0 ? 'futureRelativeFormat' : 'pastRelativeFormat');
443
+ },
444
+
445
+ duration: function(ms) {
446
+ return this.convertAdjustedToFormat(getAdjustedUnit(ms), 'durationFormat');
447
+ },
448
+
449
+ convertAdjustedToFormat: function(adu, format) {
450
+ var num = adu[0], u = adu[1], ms = adu[2], sign, unit, last, mult;
451
+ if(this['code'] == 'ru') {
452
+ last = num.toString().from(-1);
453
+ switch(true) {
454
+ case last == 1: mult = 1; break;
455
+ case last >= 2 && last <= 4: mult = 2; break;
456
+ default: mult = 3;
457
+ }
458
+ } else {
459
+ mult = this['hasPlural'] && num > 1 ? 1 : 0;
460
+ }
461
+ unit = this['units'][mult * 8 + u] || this['units'][u];
462
+ if(this['capitalizeUnit']) unit = unit.capitalize();
463
+ sign = this['modifiers'].find(function(m) { return m.name == 'sign' && m.value == (ms > 0 ? 1 : -1); });
464
+ return this[format].assign({ 'num': num, 'unit': unit, 'sign': sign.src });
465
+ },
466
+
467
+ addFormat: function(src, code, add) {
468
+ var to = [], loc = this;
469
+ if(add !== false) loc.formats.push(src);
470
+ src = src.replace(/\s+/g, '[-,. ]*');
471
+ src = src.replace(/\{(.+?)\}/g, function(all, k) {
472
+ var opt = k.match(/\?$/), slice = k.match(/(\d)(?:-(\d))?/), nc = k.match(/^\d+$/), key = k.replace(/[^a-z]+$/, ''), value, arr;
473
+ if(key === 'time') {
474
+ to = to.concat(TimeFormat);
475
+ return opt ? OptionalTime : RequiredTime;
476
+ }
477
+ if(nc) {
478
+ value = loc['optionals'][nc[0]];
479
+ } else if(loc[key]) {
480
+ value = loc[key];
481
+ } else if(loc[key + 's']) {
482
+ value = loc[key + 's'];
483
+ if(slice) {
484
+ // Can't use filter here as Prototype hijacks the method and doesn't
485
+ // pass an index, so use a simple loop instead!
486
+ arr = [];
487
+ value.forEach(function(m, i) {
488
+ var mod = i % (loc['units'] ? 8 : value.length);
489
+ if(mod >= slice[1] && mod <= (slice[2] || slice[1])) {
490
+ arr.push(m);
491
+ }
492
+ });
493
+ value = arr;
494
+ }
495
+ value = value.compact().join('|');
496
+ }
497
+ if(nc) {
498
+ return '(?:' + value + ')?';
499
+ } else {
500
+ to.push(key);
501
+ return '(' + value + ')' + (opt ? '?' : '');
502
+ }
503
+ });
504
+ addDateInputFormat(src, to, code);
505
+ }
506
+
507
+ });
508
+
509
+ function collectDateArguments(args) {
510
+ var obj, arr;
511
+ if(object.isObject(args[0])) {
512
+ return args;
513
+ } else if (args.length == 1 && object.isNumber(args[0])) {
514
+ return [args[0]];
515
+ }
516
+ obj = {};
517
+ DateArgumentUnits.each(function(u,i) {
518
+ obj[u.unit] = args[i];
519
+ });
520
+ return [obj];
521
+ }
522
+
523
+ function convertAsianDigits(str, key) {
524
+ if(key != 'date' && key != 'month' && key != 'year') return str;
525
+ return str.replace(AsianDigitReg, function(d) {
526
+ var index = LowerAsianDigits.indexOf(d);
527
+ return (index + 1) || '';
528
+ });
529
+ }
530
+
531
+ function getFormatMatch(match, arr) {
532
+ var obj = {}, value, num;
533
+ arr.each(function(key, i) {
534
+ value = match[i + 1];
535
+ if(isUndefined(value) || value === '') return;
536
+ value = convertAsianDigits(value.hankaku('n'), key);
537
+ if(key === 'year') obj.yearAsString = value;
538
+ num = parseFloat(value.replace(/,/, '.'));
539
+ obj[key] = !isNaN(num) ? num : value.toLowerCase();
540
+ });
541
+ return obj;
542
+ }
543
+
544
+ function getExtendedDate(f, locale) {
545
+ var d = new date(), relative = false, loc, variant, format, set, unit, num, tmp;
546
+ if(object.isDate(f)) {
547
+ d = f;
548
+ } else if(object.isNumber(f)) {
549
+ d = new date(f);
550
+ } else if(object.isObject(f)) {
551
+ d = new date().set(f, true);
552
+ set = f;
553
+ } else if(object.isString(f)) {
554
+ // Pre-initialize the localization formats.
555
+
556
+ checkLocaleFormatsAdded(getLocalization(locale, true));
557
+ variant = getVariant(locale);
558
+ f = f.trim().replace(/\.+$/,'').replace(/^now$/, '');
559
+ DateInputFormats.each(function(dif) {
560
+ var match = f.match(dif.reg);
561
+ if(match) {
562
+ format = dif;
563
+ set = getFormatMatch(match, format.to);
564
+ loc = getLocalization(format.locale, true);
565
+
566
+ if(set.timestamp) {
567
+ d.setTime(0);
568
+ set = { 'milliseconds': set.timestamp };
569
+ return false;
570
+ }
571
+
572
+ // If there's a European variant, swap the month and day.
573
+ if(format.variant && !object.isString(set['month']) && (object.isString(set['date']) || variant)) {
574
+ tmp = set['month'];
575
+ set['month'] = set['date'];
576
+ set['date'] = tmp;
577
+ }
578
+
579
+ // If the year is 2 digits then get the implied century.
580
+ if(set['year'] && set.yearAsString.length === 2) {
581
+ set['year'] = getYearFromAbbreviation(set['year']);
582
+ }
583
+
584
+ // Set the month which may be localized.
585
+ if(set['month']) {
586
+ set['month'] = loc.getMonth(set['month']);
587
+ if(set['shift'] && !set['unit']) set['unit'] = 'year';
588
+ }
589
+
590
+ // If there is both a weekday and a date, the date takes precedence.
591
+ if(set['weekday'] && set['date']) {
592
+ delete set['weekday'];
593
+ // Otherwise set a localized weekday.
594
+ } else if(set['weekday']) {
595
+ set['weekday'] = loc.getWeekday(set['weekday']);
596
+ if(set['shift'] && !set['unit']) set['unit'] = 'week';
597
+ }
598
+
599
+ // Relative day localizations such as "today" and "tomorrow".
600
+ if(set['day'] && (tmp = loc.modifiersByName[set['day']])) {
601
+ set['day'] = tmp.value;
602
+ d.resetTime();
603
+ relative = true;
604
+ // If the day is a weekday, then set that instead.
605
+ } else if(set['day'] && (tmp = loc.getWeekday(set['day'])) > -1) {
606
+ delete set['day'];
607
+ set['weekday'] = tmp;
608
+ }
609
+
610
+ if(set['date'] && !object.isNumber(set['date'])) {
611
+ set['date'] = loc.getNumericDate(set['date']);
612
+ }
613
+
614
+ // If the time is 1pm-11pm advance the time by 12 hours.
615
+ if(set['meridian']) {
616
+ if(set['meridian'] === 'pm' && set['hour'] < 12) set['hour'] += 12;
617
+ }
618
+
619
+ // Adjust for timezone offset
620
+ if('offset_hours' in set || 'offset_minutes' in set) {
621
+ set['utc'] = true;
622
+ set['offset_minutes'] = set['offset_minutes'] || 0;
623
+ set['offset_minutes'] += set['offset_hours'] * 60;
624
+ if(set['offset_sign'] === '-') {
625
+ set['offset_minutes'] *= -1;
626
+ }
627
+ set['minute'] -= set['offset_minutes'];
628
+ }
629
+
630
+ // Date has a unit like "days", "months", etc. are all relative to the current date.
631
+ if(set['unit']) {
632
+ relative = true;
633
+ num = loc.getNumber(set['num']);
634
+ unit = loc.getEnglishUnit(set['unit']);
635
+
636
+ // Shift and unit, ie "next month", "last week", etc.
637
+ if(set['shift'] || set['edge']) {
638
+ num *= (tmp = loc.modifiersByName[set['shift']]) ? tmp.value : 0;
639
+
640
+ // Relative month and static date: "the 15th of last month"
641
+ if(unit === 'month' && isDefined(set['date'])) {
642
+ d.set({ 'day': set['date'] }, true);
643
+ delete set['date'];
644
+ }
645
+
646
+ // Relative year and static month/date: "June 15th of last year"
647
+ if(unit === 'year' && isDefined(set['month'])) {
648
+ d.set({ 'month': set['month'], 'day': set['date'] }, true);
649
+ delete set['month'];
650
+ delete set['date'];
651
+ }
652
+ }
653
+
654
+ // Unit and sign, ie "months ago", "weeks from now", etc.
655
+ if(set['sign'] && (tmp = loc.modifiersByName[set['sign']])) {
656
+ num *= tmp.value;
657
+ }
658
+
659
+ // Units can be with non-relative dates, set here. ie "the day after monday"
660
+ if(isDefined(set['weekday'])) {
661
+ d.set({'weekday': set['weekday'] }, true);
662
+ delete set['weekday'];
663
+ }
664
+
665
+ // Finally shift the unit.
666
+ set[unit] = (set[unit] || 0) + num;
667
+ }
668
+
669
+ if(set['year_sign'] === '-') {
670
+ set['year'] *= -1;
671
+ }
672
+
673
+ DateUnitsReversed.slice(1,4).each(function(u, i) {
674
+ var value = set[u.unit], fraction = value % 1;
675
+ if(fraction) {
676
+ set[DateUnitsReversed[i].unit] = (fraction * (u.unit === 'second' ? 1000 : 60)).round();
677
+ set[u.unit] = value | 0;
678
+ }
679
+ });
680
+ return false;
681
+ }
682
+ });
683
+ if(!format) {
684
+ // The Date constructor does something tricky like checking the number
685
+ // of arguments so simply passing in undefined won't work.
686
+ d = f ? new date(f) : new date();
687
+ } else if(relative) {
688
+ d.advance(set);
689
+ } else if(set['utc']) {
690
+ // UTC times can traverse into other days or even months,
691
+ // so preemtively reset the time here to prevent this.
692
+ d.resetTime();
693
+ d.setUTC(set, true);
694
+ } else {
695
+ d.set(set, true);
696
+ }
697
+
698
+ // If there is an "edge" it needs to be set after the
699
+ // other fields are set. ie "the end of February"
700
+ if(set && set['edge']) {
701
+ tmp = loc.modifiersByName[set['edge']];
702
+ DateUnitsReversed.slice(4).each(function(u) {
703
+ if(isDefined(set[u.unit])) {
704
+ unit = u.unit;
705
+ return false;
706
+ }
707
+ });
708
+ if(unit === 'year') set.specificity = 'month';
709
+ else if(unit === 'month' || unit === 'week') set.specificity = 'day';
710
+ d[(tmp.value < 0 ? 'endOf' : 'beginningOf') + unit.capitalize()]();
711
+ // This value of -2 is arbitrary but it's a nice clean way to hook into this system.
712
+ if(tmp.value === -2) d.resetTime();
713
+ }
714
+ }
715
+ return {
716
+ date: d,
717
+ set: set
718
+ }
719
+ }
720
+
721
+ function formatDate(date, f, relative, locale) {
722
+ var adu, loc = getLocalization(locale, true), caps = regexp(/^[A-Z]/), value, l;
723
+ if(!date.isValid()) {
724
+ return 'Invalid Date';
725
+ } else if(Date[f]) {
726
+ f = Date[f];
727
+ } else if(object.isFunction(f)) {
728
+ adu = getAdjustedUnit(date.millisecondsFromNow());
729
+ f = f.apply(date, adu.concat(loc));
730
+ }
731
+ if(!f && !relative) {
732
+ f = loc['outputFormat'];
733
+ } else if(!f && relative) {
734
+ adu = adu || getAdjustedUnit(date.millisecondsFromNow());
735
+ // Adjust up if time is in ms, as this doesn't
736
+ // look very good for a standard relative date.
737
+ if(adu[1] === 0) {
738
+ adu[1] = 1;
739
+ adu[0] = 1;
740
+ }
741
+ return loc.relative(adu);
742
+ }
743
+ DateOutputFormats.each(function(dof) {
744
+ f = f.replace(regexp('\\{('+dof.token+')(\\d)?\\}', dof.word ? 'i' : ''), function(m,t,d) {
745
+ var val = dof.format(date, loc, d || 1, t), l = t.length, one = t.match(/^(.)\1+$/);
746
+ if(dof.word) {
747
+ if(l === 3) val = val.to(3);
748
+ if(one || t.match(caps)) val = val.capitalize();
749
+ } else if(one && !dof.text) {
750
+ val = (object.isNumber(val) ? val.pad(l) : val.toString()).last(l);
751
+ }
752
+ return val;
753
+ });
754
+ });
755
+ return f;
756
+ }
757
+
758
+ function compareDate(d, find, buffer) {
759
+ var p = getExtendedDate(find), accuracy = 0, loBuffer = 0, hiBuffer = 0, override;
760
+ if(buffer > 0) {
761
+ loBuffer = hiBuffer = buffer;
762
+ override = true;
763
+ }
764
+ if(!p.date.isValid()) return false;
765
+ if(p.set && p.set.specificity) {
766
+ DateUnits.each(function(u, i) {
767
+ if(u.unit === p.set.specificity) {
768
+ accuracy = u.multiplier(p.date, d - p.date) - 1;
769
+ }
770
+ });
771
+ if(p.set['edge'] || p.set['shift']) {
772
+ p.date['beginningOf' + p.set.specificity.capitalize()]();
773
+ }
774
+ if(!override && p.set['sign'] && p.set.specificity != 'millisecond') {
775
+ // If the time is relative, there can occasionally be an disparity between the relative date
776
+ // and "now", which it is being compared to, so set an extra buffer to account for this.
777
+ loBuffer = 50;
778
+ hiBuffer = -50;
779
+ }
780
+ }
781
+ var t = d.getTime();
782
+ var min = p.date.getTime();
783
+ var max = min + accuracy;
784
+ if(p.set && p.set.specificity == 'week' && new Date(max + 1).getHours() != 0) {
785
+ max += date['DSTOffset'];
786
+ }
787
+ return t >= (min - loBuffer) && t <= (max + hiBuffer);
788
+ }
789
+
790
+ function updateDate(date, params, reset, utc, advance) {
791
+ if(object.isNumber(params) && advance) {
792
+ // If param is a number and we're advancing, the number is presumed to be milliseconds.
793
+ params = { 'milliseconds': params };
794
+ } else if(object.isNumber(params)) {
795
+ // Otherwise just set the timestamp and return.
796
+ date.setTime(params);
797
+ return date;
798
+ }
799
+
800
+ // "date" can also be passed for the day
801
+ if(params['date']) params['day'] = params['date'];
802
+ // If a weekday is included in the params, set it ahead of time and set the params
803
+ // to reflect the updated date so that resetting works properly.
804
+ if(!advance && isUndefined(params['day']) && isDefined(params['weekday'])) {
805
+ callDateMethod(date, 'set', utc, 'Weekday', params['weekday'])
806
+ params['day'] = callDateMethod(date, 'get', utc, 'Date');
807
+ delete params['weekday'];
808
+ }
809
+ // Reset any unit lower than the least specific unit set. Do not do this for weeks
810
+ // or for years. This needs to be performed before the acutal setting of the date
811
+ // because the order needs to be reversed in order to get the lowest specificity.
812
+ // The order of the date setting is also fixed because higher order units can be
813
+ // overwritten by lower order units, such as setting hour: 3, minute: 345, etc.
814
+ DateUnitsReversed.each(function(u) {
815
+ if(isDefined(params[u.unit]) || isDefined(params[u.unit + 's'])) {
816
+ params.specificity = u.unit;
817
+ return false;
818
+ } else if(reset && u.unit !== 'week' && u.unit !== 'year') {
819
+ callDateMethod(date, 'set', utc, u.method, (u.unit === 'day') ? 1 : 0);
820
+ }
821
+ });
822
+ // Now actually set or advance the date in order, higher units first.
823
+ DateUnits.each(function(u,i) {
824
+ var unit = u.unit;
825
+ var method = u.method;
826
+ var value = isDefined(params[unit]) ? params[unit] : params[unit + 's'];
827
+ if(isUndefined(value)) return;
828
+ if(advance) {
829
+ if(unit === 'week') {
830
+ value = (params['day'] || 0) + (value * 7);
831
+ method = 'Date';
832
+ }
833
+ value = (value * advance) + callDateMethod(date, 'get', '', method);
834
+ }
835
+ callDateMethod(date, 'set', utc, method, value);
836
+ if(unit === 'month') {
837
+ checkMonthTraversal(date, value);
838
+ }
839
+ });
840
+ return date;
841
+ }
842
+
843
+ function callDateMethod(d, prefix, utc, method, value) {
844
+ return d[prefix + (utc ? 'UTC' : '') + method](value);
845
+ }
846
+
847
+ // If the year is two digits, add the most appropriate century prefix.
848
+ function getYearFromAbbreviation(year) {
849
+ return (new date().getFullYear() / 100).round() * 100 - (year / 100).round() * 100 + year;
850
+ }
851
+
852
+ function getShortHour(d, utc) {
853
+ var hours = callDateMethod(d, 'get', utc, 'Hours');
854
+ return hours === 0 ? 12 : hours - ((hours / 13 | 0) * 12);
855
+ }
856
+
857
+ function getMeridian(d, utc) {
858
+ var hours = callDateMethod(d, 'get', utc, 'Hours');
859
+ return hours < 12 ? 'am' : 'pm';
860
+ }
861
+
862
+ // weeksSince won't work here as the result needs to be floored, not rounded.
863
+ function getWeekNumber(date) {
864
+ var dow = date.getDay() || 7;
865
+ date.addDays(4 - dow).resetTime();
866
+ return 1 + (date.daysSince(date.clone().beginningOfYear()) / 7 | 0);
867
+ }
868
+
869
+ function getAdjustedUnit(ms) {
870
+ var next, ams = ms.abs(), value = ams, unit = 0;
871
+ DateUnitsReversed.from(1).each(function(u, i) {
872
+ next = (ams / u.multiplier() * 10).round() / 10 | 0;
873
+ if(next >= 1) {
874
+ value = next;
875
+ unit = i + 1;
876
+ }
877
+ });
878
+ return [value, unit, ms];
879
+ }
880
+
881
+
882
+ // If the month is being set, then we don't want to accidentally
883
+ // traverse into a new month just because the target month doesn't have enough
884
+ // days. In other words, "5 months ago" from July 30th is still February, even
885
+ // though there is no February 30th, so it will of necessity be February 28th
886
+ // (or 29th in the case of a leap year).
887
+
888
+ function checkMonthTraversal(date, targetMonth) {
889
+ if(targetMonth < 0) targetMonth += 12;
890
+ if(targetMonth % 12 != date.getMonth()) {
891
+ date.setDate(0);
892
+ }
893
+ }
894
+
895
+ function createDate(args) {
896
+ var f;
897
+ if(object.isNumber(args[1])) {
898
+ // If the second argument is a number, then we have an enumerated constructor type as in "new Date(2003, 2, 12);"
899
+ f = collectDateArguments(args)[0];
900
+ } else {
901
+ f = args[0];
902
+ }
903
+ return getExtendedDate(f, args[1]).date;
904
+ }
905
+
906
+
907
+
908
+ /***
909
+ * @method [units]Since([d], [locale] = currentLocale)
910
+ * @returns Number
911
+ * @short Returns the time since [d] in the appropriate unit.
912
+ * @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. For more see @date_format.
913
+ * @example
914
+ *
915
+ * Date.create().millisecondsSince('1 hour ago') -> 3,600,000
916
+ * Date.create().daysSince('1 week ago') -> 7
917
+ * Date.create().yearsSince('15 years ago') -> 15
918
+ * Date.create('15 years ago').yearsAgo() -> 15
919
+ *
920
+ ***
921
+ * @method millisecondsSince()
922
+ * @set unitsSince
923
+ ***
924
+ * @method secondsSince()
925
+ * @set unitsSince
926
+ ***
927
+ * @method minutesSince()
928
+ * @set unitsSince
929
+ ***
930
+ * @method hoursSince()
931
+ * @set unitsSince
932
+ ***
933
+ * @method daysSince()
934
+ * @set unitsSince
935
+ ***
936
+ * @method weeksSince()
937
+ * @set unitsSince
938
+ ***
939
+ * @method monthsSince()
940
+ * @set unitsSince
941
+ ***
942
+ * @method yearsSince()
943
+ * @set unitsSince
944
+ ***
945
+ * @method [units]Ago()
946
+ * @returns Number
947
+ * @short Returns the time ago in the appropriate unit.
948
+ * @example
949
+ *
950
+ * Date.create('last year').millisecondsAgo() -> 3,600,000
951
+ * Date.create('last year').daysAgo() -> 7
952
+ * Date.create('last year').yearsAgo() -> 15
953
+ *
954
+ ***
955
+ * @method millisecondsAgo()
956
+ * @set unitsAgo
957
+ ***
958
+ * @method secondsAgo()
959
+ * @set unitsAgo
960
+ ***
961
+ * @method minutesAgo()
962
+ * @set unitsAgo
963
+ ***
964
+ * @method hoursAgo()
965
+ * @set unitsAgo
966
+ ***
967
+ * @method daysAgo()
968
+ * @set unitsAgo
969
+ ***
970
+ * @method weeksAgo()
971
+ * @set unitsAgo
972
+ ***
973
+ * @method monthsAgo()
974
+ * @set unitsAgo
975
+ ***
976
+ * @method yearsAgo()
977
+ * @set unitsAgo
978
+ ***
979
+ * @method [units]Until([d], [locale] = currentLocale)
980
+ * @returns Number
981
+ * @short Returns the time until [d] in the appropriate unit.
982
+ * @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. For more see @date_format.
983
+ * @example
984
+ *
985
+ * Date.create().millisecondsUntil('1 hour from now') -> 3,600,000
986
+ * Date.create().daysUntil('1 week from now') -> 7
987
+ * Date.create().yearsUntil('15 years from now') -> 15
988
+ * Date.create('15 years from now').yearsFromNow() -> 15
989
+ *
990
+ ***
991
+ * @method millisecondsUntil()
992
+ * @set unitsUntil
993
+ ***
994
+ * @method secondsUntil()
995
+ * @set unitsUntil
996
+ ***
997
+ * @method minutesUntil()
998
+ * @set unitsUntil
999
+ ***
1000
+ * @method hoursUntil()
1001
+ * @set unitsUntil
1002
+ ***
1003
+ * @method daysUntil()
1004
+ * @set unitsUntil
1005
+ ***
1006
+ * @method weeksUntil()
1007
+ * @set unitsUntil
1008
+ ***
1009
+ * @method monthsUntil()
1010
+ * @set unitsUntil
1011
+ ***
1012
+ * @method yearsUntil()
1013
+ * @set unitsUntil
1014
+ ***
1015
+ * @method [units]FromNow()
1016
+ * @returns Number
1017
+ * @short Returns the time from now in the appropriate unit.
1018
+ * @example
1019
+ *
1020
+ * Date.create('next year').millisecondsFromNow() -> 3,600,000
1021
+ * Date.create('next year').daysFromNow() -> 7
1022
+ * Date.create('next year').yearsFromNow() -> 15
1023
+ *
1024
+ ***
1025
+ * @method millisecondsFromNow()
1026
+ * @set unitsFromNow
1027
+ ***
1028
+ * @method secondsFromNow()
1029
+ * @set unitsFromNow
1030
+ ***
1031
+ * @method minutesFromNow()
1032
+ * @set unitsFromNow
1033
+ ***
1034
+ * @method hoursFromNow()
1035
+ * @set unitsFromNow
1036
+ ***
1037
+ * @method daysFromNow()
1038
+ * @set unitsFromNow
1039
+ ***
1040
+ * @method weeksFromNow()
1041
+ * @set unitsFromNow
1042
+ ***
1043
+ * @method monthsFromNow()
1044
+ * @set unitsFromNow
1045
+ ***
1046
+ * @method yearsFromNow()
1047
+ * @set unitsFromNow
1048
+ ***
1049
+ * @method add[Units](<num>)
1050
+ * @returns Date
1051
+ * @short Adds <num> of the unit to the date.
1052
+ * @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 this method if you need precision.
1053
+ * @example
1054
+ *
1055
+ * Date.create().addMilliseconds(5) -> current time + 5 milliseconds
1056
+ * Date.create().addDays(5) -> current time + 5 days
1057
+ * Date.create().addYears(5) -> current time + 5 years
1058
+ *
1059
+ ***
1060
+ * @method addMilliseconds()
1061
+ * @set addUnits
1062
+ ***
1063
+ * @method addSeconds()
1064
+ * @set addUnits
1065
+ ***
1066
+ * @method addMinutes()
1067
+ * @set addUnits
1068
+ ***
1069
+ * @method addHours()
1070
+ * @set addUnits
1071
+ ***
1072
+ * @method addDays()
1073
+ * @set addUnits
1074
+ ***
1075
+ * @method addWeeks()
1076
+ * @set addUnits
1077
+ ***
1078
+ * @method addMonths()
1079
+ * @set addUnits
1080
+ ***
1081
+ * @method addYears()
1082
+ * @set addUnits
1083
+ ***
1084
+ * @method isLast[Unit]()
1085
+ * @returns Boolean
1086
+ * @short Returns true if the date is last week/month/year.
1087
+ * @example
1088
+ *
1089
+ * Date.create('yesterday').isLastWeek() -> true or false?
1090
+ * Date.create('yesterday').isLastMonth() -> probably not...
1091
+ * Date.create('yesterday').isLastYear() -> even less likely...
1092
+ *
1093
+ ***
1094
+ * @method isThis[Unit]()
1095
+ * @returns Boolean
1096
+ * @short Returns true if the date is this week/month/year.
1097
+ * @example
1098
+ *
1099
+ * Date.create('tomorrow').isThisWeek() -> true or false?
1100
+ * Date.create('tomorrow').isThisMonth() -> probably...
1101
+ * Date.create('tomorrow').isThisYear() -> signs point to yes...
1102
+ *
1103
+ ***
1104
+ * @method isNext[Unit]()
1105
+ * @returns Boolean
1106
+ * @short Returns true if the date is next week/month/year.
1107
+ * @example
1108
+ *
1109
+ * Date.create('tomorrow').isNextWeek() -> true or false?
1110
+ * Date.create('tomorrow').isNextMonth() -> probably not...
1111
+ * Date.create('tomorrow').isNextYear() -> even less likely...
1112
+ *
1113
+ ***
1114
+ * @method isLastWeek()
1115
+ * @set isLastUnit
1116
+ ***
1117
+ * @method isLastMonth()
1118
+ * @set isLastUnit
1119
+ ***
1120
+ * @method isLastYear()
1121
+ * @set isLastUnit
1122
+ ***
1123
+ * @method isThisWeek()
1124
+ * @set isThisUnit
1125
+ ***
1126
+ * @method isThisMonth()
1127
+ * @set isThisUnit
1128
+ ***
1129
+ * @method isThisYear()
1130
+ * @set isThisUnit
1131
+ ***
1132
+ * @method isNextWeek()
1133
+ * @set isNextUnit
1134
+ ***
1135
+ * @method isNextMonth()
1136
+ * @set isNextUnit
1137
+ ***
1138
+ * @method isNextYear()
1139
+ * @set isNextUnit
1140
+ ***
1141
+ * @method beginningOf[Unit]()
1142
+ * @returns Date
1143
+ * @short Sets the date to the beginning of the appropriate unit.
1144
+ * @example
1145
+ *
1146
+ * Date.create().beginningOfDay() -> the beginning of today (resets the time)
1147
+ * Date.create().beginningOfWeek() -> the beginning of the week
1148
+ * Date.create().beginningOfMonth() -> the beginning of the month
1149
+ * Date.create().beginningOfYear() -> the beginning of the year
1150
+ *
1151
+ ***
1152
+ * @method endOf[Unit]()
1153
+ * @returns Date
1154
+ * @short Sets the date to the end of the appropriate unit.
1155
+ * @example
1156
+ *
1157
+ * Date.create().endOfDay() -> the end of today (sets the time to 23:59:59.999)
1158
+ * Date.create().endOfWeek() -> the end of the week
1159
+ * Date.create().endOfMonth() -> the end of the month
1160
+ * Date.create().endOfYear() -> the end of the year
1161
+ *
1162
+ ***
1163
+ * @method beginningOfDay()
1164
+ * @set beginningOfUnit
1165
+ ***
1166
+ * @method beginningOfWeek()
1167
+ * @set beginningOfUnit
1168
+ ***
1169
+ * @method beginningOfMonth()
1170
+ * @set beginningOfUnit
1171
+ ***
1172
+ * @method beginningOfYear()
1173
+ * @set beginningOfUnit
1174
+ ***
1175
+ * @method endOfDay()
1176
+ * @set endOfUnit
1177
+ ***
1178
+ * @method endOfWeek()
1179
+ * @set endOfUnit
1180
+ ***
1181
+ * @method endOfMonth()
1182
+ * @set endOfUnit
1183
+ ***
1184
+ * @method endOfYear()
1185
+ * @set endOfUnit
1186
+ ***/
1187
+ function buildDateMethods() {
1188
+ var methods = {};
1189
+ DateUnits.each(function(u, i) {
1190
+ var unit = u.unit;
1191
+ var caps = unit.capitalize();
1192
+ var multiplier = u.multiplier();
1193
+ var since = function(f, code) {
1194
+ return ((this.getTime() - date.create(f, code).getTime()) / multiplier).round();
1195
+ };
1196
+ var until = function(f, code) {
1197
+ return ((date.create(f, code).getTime() - this.getTime()) / multiplier).round();
1198
+ };
1199
+ methods[unit+'sAgo'] = until;
1200
+ methods[unit+'sUntil'] = until;
1201
+ methods[unit+'sSince'] = since;
1202
+ methods[unit+'sFromNow'] = since;
1203
+ methods['add'+caps+'s'] = function(num) {
1204
+ var set = {};
1205
+ set[unit] = num;
1206
+ return this.advance(set);
1207
+ };
1208
+ buildNumberToDateAlias(unit, multiplier);
1209
+ if(i < 3) {
1210
+ ['Last','This','Next'].each(function(shift) {
1211
+ methods['is' + shift + caps] = function() {
1212
+ return this.is(shift + ' ' + unit);
1213
+ };
1214
+ });
1215
+ }
1216
+ if(i < 4) {
1217
+ methods['beginningOf' + caps] = function() {
1218
+ var set = {};
1219
+ switch(unit) {
1220
+ case 'year': set['year'] = this.getFullYear(); break;
1221
+ case 'month': set['month'] = this.getMonth(); break;
1222
+ case 'day': set['day'] = this.getDate(); break;
1223
+ case 'week': set['weekday'] = 0; break;
1224
+ }
1225
+ return this.set(set, true);
1226
+ };
1227
+ methods['endOf' + caps] = function() {
1228
+ var set = { 'hours': 23, 'minutes': 59, 'seconds': 59, 'milliseconds': 999 };
1229
+ switch(unit) {
1230
+ case 'year': set['month'] = 11; set['day'] = 31; break;
1231
+ case 'month': set['day'] = this.daysInMonth(); break;
1232
+ case 'week': set['weekday'] = 6; break;
1233
+ }
1234
+ return this.set(set, true);
1235
+ };
1236
+ }
1237
+ });
1238
+ date.extend(methods);
1239
+ }
1240
+
1241
+ function buildDateInputFormats() {
1242
+ DateArgumentUnits = DateUnits.clone().removeAt(2);
1243
+ DateUnitsReversed = DateUnits.clone().reverse();
1244
+ var monthReg = '\\d{1,2}|' + English['months'].join('|');
1245
+ StaticInputFormats.each(function(f) {
1246
+ addDateInputFormat(f.src.replace(/\{month\}/, monthReg) + (f.time === false ? '' : OptionalTime), f.to.concat(TimeFormat), 'en', f.variant);
1247
+ });
1248
+ addDateInputFormat(RequiredTime, TimeFormat);
1249
+ }
1250
+
1251
+ /***
1252
+ * @method is[Day]()
1253
+ * @returns Boolean
1254
+ * @short Returns true if the date falls on that day.
1255
+ * @extra Also available: %isYesterday%, %isToday%, %isTomorrow%, %isWeekday%, and %isWeekend%.
1256
+ * @example
1257
+ *
1258
+ * Date.create('tomorrow').isToday() -> false
1259
+ * Date.create('thursday').isTomorrow() -> ?
1260
+ * Date.create('yesterday').isWednesday() -> ?
1261
+ * Date.create('today').isWeekend() -> ?
1262
+ *
1263
+ ***
1264
+ * @method isToday()
1265
+ * @set isDay
1266
+ ***
1267
+ * @method isYesterday()
1268
+ * @set isDay
1269
+ ***
1270
+ * @method isTomorrow()
1271
+ * @set isDay
1272
+ ***
1273
+ * @method isWeekday()
1274
+ * @set isDay
1275
+ ***
1276
+ * @method isWeekend()
1277
+ * @set isDay
1278
+ ***
1279
+ * @method isSunday()
1280
+ * @set isDay
1281
+ ***
1282
+ * @method isMonday()
1283
+ * @set isDay
1284
+ ***
1285
+ * @method isTuesday()
1286
+ * @set isDay
1287
+ ***
1288
+ * @method isWednesday()
1289
+ * @set isDay
1290
+ ***
1291
+ * @method isThursday()
1292
+ * @set isDay
1293
+ ***
1294
+ * @method isFriday()
1295
+ * @set isDay
1296
+ ***
1297
+ * @method isSaturday()
1298
+ * @set isDay
1299
+ ***
1300
+ * @method isFuture()
1301
+ * @returns Boolean
1302
+ * @short Returns true if the date is in the future.
1303
+ * @example
1304
+ *
1305
+ * Date.create('next week').isFuture() -> true
1306
+ * Date.create('last week').isFuture() -> false
1307
+ *
1308
+ ***
1309
+ * @method isPast()
1310
+ * @returns Boolean
1311
+ * @short Returns true if the date is in the past.
1312
+ * @example
1313
+ *
1314
+ * Date.create('last week').isPast() -> true
1315
+ * Date.create('next week').isPast() -> false
1316
+ *
1317
+ ***/
1318
+ function buildRelativeAliases() {
1319
+ var methods = {};
1320
+ var weekdays = English['weekdays'].slice(0,7);
1321
+ var months = English['months'].slice(0,12);
1322
+ ['today','yesterday','tomorrow','weekday','weekend','future','past'].concat(weekdays).concat(months).each(function(s) {
1323
+ methods['is'+ s.capitalize()] = function() {
1324
+ return this.is(s);
1325
+ };
1326
+ });
1327
+ date.extend(methods);
1328
+ }
1329
+
1330
+ /***
1331
+ * @method [unit]()
1332
+ * @returns Number
1333
+ * @short Takes the number as a corresponding unit of time and converts to milliseconds.
1334
+ * @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.
1335
+ * @example
1336
+ *
1337
+ * (5).milliseconds() -> 5
1338
+ * (10).hours() -> 36000000
1339
+ * (1).day() -> 86400000
1340
+ *
1341
+ ***
1342
+ * @method millisecond()
1343
+ * @set unit
1344
+ ***
1345
+ * @method milliseconds()
1346
+ * @set unit
1347
+ ***
1348
+ * @method second()
1349
+ * @set unit
1350
+ ***
1351
+ * @method seconds()
1352
+ * @set unit
1353
+ ***
1354
+ * @method minute()
1355
+ * @set unit
1356
+ ***
1357
+ * @method minutes()
1358
+ * @set unit
1359
+ ***
1360
+ * @method hour()
1361
+ * @set unit
1362
+ ***
1363
+ * @method hours()
1364
+ * @set unit
1365
+ ***
1366
+ * @method day()
1367
+ * @set unit
1368
+ ***
1369
+ * @method days()
1370
+ * @set unit
1371
+ ***
1372
+ * @method week()
1373
+ * @set unit
1374
+ ***
1375
+ * @method weeks()
1376
+ * @set unit
1377
+ ***
1378
+ * @method month()
1379
+ * @set unit
1380
+ ***
1381
+ * @method months()
1382
+ * @set unit
1383
+ ***
1384
+ * @method year()
1385
+ * @set unit
1386
+ ***
1387
+ * @method years()
1388
+ * @set unit
1389
+ ***
1390
+ * @method [unit]Before([d], [locale] = currentLocale)
1391
+ * @returns Date
1392
+ * @short Returns a date that is <n> units before [d], where <n> is the number.
1393
+ * @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 information.
1394
+ * @example
1395
+ *
1396
+ * (5).daysBefore('tuesday') -> 5 days before tuesday of this week
1397
+ * (1).yearBefore('January 23, 1997') -> January 23, 1996
1398
+ *
1399
+ ***
1400
+ * @method millisecondBefore()
1401
+ * @set unitBefore
1402
+ ***
1403
+ * @method millisecondsBefore()
1404
+ * @set unitBefore
1405
+ ***
1406
+ * @method secondBefore()
1407
+ * @set unitBefore
1408
+ ***
1409
+ * @method secondsBefore()
1410
+ * @set unitBefore
1411
+ ***
1412
+ * @method minuteBefore()
1413
+ * @set unitBefore
1414
+ ***
1415
+ * @method minutesBefore()
1416
+ * @set unitBefore
1417
+ ***
1418
+ * @method hourBefore()
1419
+ * @set unitBefore
1420
+ ***
1421
+ * @method hoursBefore()
1422
+ * @set unitBefore
1423
+ ***
1424
+ * @method dayBefore()
1425
+ * @set unitBefore
1426
+ ***
1427
+ * @method daysBefore()
1428
+ * @set unitBefore
1429
+ ***
1430
+ * @method weekBefore()
1431
+ * @set unitBefore
1432
+ ***
1433
+ * @method weeksBefore()
1434
+ * @set unitBefore
1435
+ ***
1436
+ * @method monthBefore()
1437
+ * @set unitBefore
1438
+ ***
1439
+ * @method monthsBefore()
1440
+ * @set unitBefore
1441
+ ***
1442
+ * @method yearBefore()
1443
+ * @set unitBefore
1444
+ ***
1445
+ * @method yearsBefore()
1446
+ * @set unitBefore
1447
+ ***
1448
+ * @method [unit]Ago()
1449
+ * @returns Date
1450
+ * @short Returns a date that is <n> units ago.
1451
+ * @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.
1452
+ * @example
1453
+ *
1454
+ * (5).weeksAgo() -> 5 weeks ago
1455
+ * (1).yearAgo() -> January 23, 1996
1456
+ *
1457
+ ***
1458
+ * @method millisecondAgo()
1459
+ * @set unitAgo
1460
+ ***
1461
+ * @method millisecondsAgo()
1462
+ * @set unitAgo
1463
+ ***
1464
+ * @method secondAgo()
1465
+ * @set unitAgo
1466
+ ***
1467
+ * @method secondsAgo()
1468
+ * @set unitAgo
1469
+ ***
1470
+ * @method minuteAgo()
1471
+ * @set unitAgo
1472
+ ***
1473
+ * @method minutesAgo()
1474
+ * @set unitAgo
1475
+ ***
1476
+ * @method hourAgo()
1477
+ * @set unitAgo
1478
+ ***
1479
+ * @method hoursAgo()
1480
+ * @set unitAgo
1481
+ ***
1482
+ * @method dayAgo()
1483
+ * @set unitAgo
1484
+ ***
1485
+ * @method daysAgo()
1486
+ * @set unitAgo
1487
+ ***
1488
+ * @method weekAgo()
1489
+ * @set unitAgo
1490
+ ***
1491
+ * @method weeksAgo()
1492
+ * @set unitAgo
1493
+ ***
1494
+ * @method monthAgo()
1495
+ * @set unitAgo
1496
+ ***
1497
+ * @method monthsAgo()
1498
+ * @set unitAgo
1499
+ ***
1500
+ * @method yearAgo()
1501
+ * @set unitAgo
1502
+ ***
1503
+ * @method yearsAgo()
1504
+ * @set unitAgo
1505
+ ***
1506
+ * @method [unit]After([d], [locale] = currentLocale)
1507
+ * @returns Date
1508
+ * @short Returns a date <n> units after [d], where <n> is the number.
1509
+ * @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 information.
1510
+ * @example
1511
+ *
1512
+ * (5).daysAfter('tuesday') -> 5 days after tuesday of this week
1513
+ * (1).yearAfter('January 23, 1997') -> January 23, 1998
1514
+ *
1515
+ ***
1516
+ * @method millisecondAfter()
1517
+ * @set unitAfter
1518
+ ***
1519
+ * @method millisecondsAfter()
1520
+ * @set unitAfter
1521
+ ***
1522
+ * @method secondAfter()
1523
+ * @set unitAfter
1524
+ ***
1525
+ * @method secondsAfter()
1526
+ * @set unitAfter
1527
+ ***
1528
+ * @method minuteAfter()
1529
+ * @set unitAfter
1530
+ ***
1531
+ * @method minutesAfter()
1532
+ * @set unitAfter
1533
+ ***
1534
+ * @method hourAfter()
1535
+ * @set unitAfter
1536
+ ***
1537
+ * @method hoursAfter()
1538
+ * @set unitAfter
1539
+ ***
1540
+ * @method dayAfter()
1541
+ * @set unitAfter
1542
+ ***
1543
+ * @method daysAfter()
1544
+ * @set unitAfter
1545
+ ***
1546
+ * @method weekAfter()
1547
+ * @set unitAfter
1548
+ ***
1549
+ * @method weeksAfter()
1550
+ * @set unitAfter
1551
+ ***
1552
+ * @method monthAfter()
1553
+ * @set unitAfter
1554
+ ***
1555
+ * @method monthsAfter()
1556
+ * @set unitAfter
1557
+ ***
1558
+ * @method yearAfter()
1559
+ * @set unitAfter
1560
+ ***
1561
+ * @method yearsAfter()
1562
+ * @set unitAfter
1563
+ ***
1564
+ * @method [unit]FromNow()
1565
+ * @returns Date
1566
+ * @short Returns a date <n> units from now.
1567
+ * @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.
1568
+ * @example
1569
+ *
1570
+ * (5).weeksFromNow() -> 5 weeks ago
1571
+ * (1).yearFromNow() -> January 23, 1998
1572
+ *
1573
+ ***
1574
+ * @method millisecondFromNow()
1575
+ * @set unitFromNow
1576
+ ***
1577
+ * @method millisecondsFromNow()
1578
+ * @set unitFromNow
1579
+ ***
1580
+ * @method secondFromNow()
1581
+ * @set unitFromNow
1582
+ ***
1583
+ * @method secondsFromNow()
1584
+ * @set unitFromNow
1585
+ ***
1586
+ * @method minuteFromNow()
1587
+ * @set unitFromNow
1588
+ ***
1589
+ * @method minutesFromNow()
1590
+ * @set unitFromNow
1591
+ ***
1592
+ * @method hourFromNow()
1593
+ * @set unitFromNow
1594
+ ***
1595
+ * @method hoursFromNow()
1596
+ * @set unitFromNow
1597
+ ***
1598
+ * @method dayFromNow()
1599
+ * @set unitFromNow
1600
+ ***
1601
+ * @method daysFromNow()
1602
+ * @set unitFromNow
1603
+ ***
1604
+ * @method weekFromNow()
1605
+ * @set unitFromNow
1606
+ ***
1607
+ * @method weeksFromNow()
1608
+ * @set unitFromNow
1609
+ ***
1610
+ * @method monthFromNow()
1611
+ * @set unitFromNow
1612
+ ***
1613
+ * @method monthsFromNow()
1614
+ * @set unitFromNow
1615
+ ***
1616
+ * @method yearFromNow()
1617
+ * @set unitFromNow
1618
+ ***
1619
+ * @method yearsFromNow()
1620
+ * @set unitFromNow
1621
+ ***/
1622
+ function buildNumberToDateAlias(unit, multiplier) {
1623
+ var add = 'add' + unit.capitalize() + 's', methods = {};
1624
+ function base() { return (this * multiplier).round(); }
1625
+ function after() { return createDate(arguments)[add](this); }
1626
+ function before() { return createDate(arguments)[add](-this); }
1627
+ methods[unit] = base;
1628
+ methods[unit + 's'] = base;
1629
+ methods[unit + 'Before'] = before;
1630
+ methods[unit + 'sBefore'] = before;
1631
+ methods[unit + 'Ago'] = before;
1632
+ methods[unit + 'sAgo'] = before;
1633
+ methods[unit + 'After'] = after;
1634
+ methods[unit + 'sAfter'] = after;
1635
+ methods[unit + 'FromNow'] = after;
1636
+ methods[unit + 'sFromNow'] = after;
1637
+ number.extend(methods);
1638
+ }
1639
+
1640
+ function setDateProperties() {
1641
+ date.extend({
1642
+ 'DSTOffset': (new date(2000, 6, 1).getTimezoneOffset() - new date(2000, 0, 1).getTimezoneOffset()) * 60 * 1000,
1643
+ 'INTERNATIONAL_TIME': '{h}:{mm}:{ss}',
1644
+ 'RFC1123': '{Dow}, {dd} {Mon} {yyyy} {HH}:{mm}:{ss} {tz}',
1645
+ 'RFC1036': '{Weekday}, {dd}-{Mon}-{yy} {HH}:{mm}:{ss} {tz}',
1646
+ 'ISO8601_DATE': '{yyyy}-{MM}-{dd}',
1647
+ 'ISO8601_DATETIME': '{yyyy}-{MM}-{dd}T{HH}:{mm}:{ss}.{fff}{isotz}'
1648
+ }, false, false);
1649
+ }
1650
+
1651
+
1652
+ /***
1653
+ * @method toISOString()
1654
+ * @returns String
1655
+ * @short Formats the string to ISO8601 format.
1656
+ * @extra This will always format as UTC time. Provided for browsers that do not support this method.
1657
+ * @example
1658
+ *
1659
+ * Date.create().toISOString() -> ex. 2011-07-05 12:24:55.528Z
1660
+ *
1661
+ ***
1662
+ * @method toJSON()
1663
+ * @returns String
1664
+ * @short Returns a JSON representation of the date.
1665
+ * @extra This is effectively an alias for %toISOString%. Will always return the date in UTC time. Implemented for browsers that do not support it.
1666
+ * @example
1667
+ *
1668
+ * Date.create().toJSON() -> ex. 2011-07-05 12:24:55.528Z
1669
+ *
1670
+ ***/
1671
+
1672
+ function buildISOString(name) {
1673
+ var d = new date(date.UTC(1999, 11, 31)), target = '1999-12-31T00:00:00.000Z', methods = {};
1674
+ if(!d[name] || d[name]() !== target) {
1675
+ methods[name] = function() { return formatDate(this.toUTC(), date['ISO8601_DATETIME']); }
1676
+ date.extend(methods, true);
1677
+ }
1678
+ }
1679
+
1680
+ function buildDate() {
1681
+ English = date.setLocale('en');
1682
+ buildDateMethods();
1683
+ buildDateInputFormats();
1684
+ buildRelativeAliases();
1685
+ buildISOString('toISOString');
1686
+ buildISOString('toJSON');
1687
+ setDateProperties();
1688
+ }
1689
+
1690
+
1691
+ date.extend({
1692
+
1693
+ /***
1694
+ * @method Date.create(<d>, [locale] = currentLocale)
1695
+ * @returns Date
1696
+ * @short Alternate Date constructor which understands various formats.
1697
+ * @extra Accepts a multitude of text formats, a timestamp, or another date. 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. For more information, see @date_format.
1698
+ * @example
1699
+ *
1700
+ * Date.create('July') -> July of this year
1701
+ * Date.create('1776') -> 1776
1702
+ * Date.create('today') -> today
1703
+ * Date.create('wednesday') -> This wednesday
1704
+ * Date.create('next friday') -> Next friday
1705
+ * Date.create('July 4, 1776') -> July 4, 1776
1706
+ * Date.create(-446806800000) -> November 5, 1955
1707
+ * Date.create(1776, 6, 4) -> July 4, 1776
1708
+ * Date.create('1776年07月04日', 'ja') -> July 4, 1776
1709
+ *
1710
+ ***/
1711
+ 'create': function() {
1712
+ return createDate(arguments);
1713
+ },
1714
+
1715
+ /***
1716
+ * @method Date.now()
1717
+ * @returns String
1718
+ * @short Returns the number of milliseconds since January 1st, 1970 00:00:00 (UTC time).
1719
+ * @example
1720
+ *
1721
+ * Date.now() -> ex. 1311938296231
1722
+ *
1723
+ ***/
1724
+ 'now': function() {
1725
+ return new date().getTime();
1726
+ },
1727
+
1728
+ /***
1729
+ * @method Date.setLocale(<code>, [set])
1730
+ * @returns Locale
1731
+ * @short Sets the current locale to be used with dates.
1732
+ * @extra Predefined locales are: English (en), French (fr), Italian (it), Spanish (es), Portuguese (pt), German (de), Russian (ru), Japanese (ja), Korean (ko), Simplified Chinese (zh-CN), and Traditional Chinese (zh-TW). In addition to available major locales, you can define a new local here by passing an object for [set]. For more see @date_format.
1733
+ *
1734
+ ***/
1735
+ 'setLocale': function(code, set) {
1736
+ var loc = getLocalization(code, false, set);
1737
+ if(loc) {
1738
+ Date['currentLocale'] = code;
1739
+ checkLocaleFormatsAdded(loc);
1740
+ return loc;
1741
+ }
1742
+ },
1743
+
1744
+ /***
1745
+ * @method Date.getLocale([code] = current)
1746
+ * @returns Locale
1747
+ * @short Gets the locale for the given code, or the current locale.
1748
+ * @extra Returns undefined if there is no locale for the given code. Manipulating the locale object can give you more control over date localizations. For more about locales, see @date_format.
1749
+ *
1750
+ ***/
1751
+ 'getLocale': function(code) {
1752
+ return getLocalization(code, true);
1753
+ },
1754
+
1755
+ /***
1756
+ * @method Date.addFormat(<format>, <match>, [locale] = null)
1757
+ * @returns Nothing
1758
+ * @short Manually adds a new date input format.
1759
+ * @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.
1760
+ *
1761
+ ***/
1762
+ 'addFormat': function(format, match, locale, variant) {
1763
+ addDateInputFormat(format, match, locale, variant, 'unshift');
1764
+ }
1765
+
1766
+ }, false, false);
1767
+
1768
+ date.extend({
1769
+
1770
+ /***
1771
+ * @method set(<set>, [reset] = false)
1772
+ * @returns Date
1773
+ * @short Sets the date object.
1774
+ * @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. %setUTC% will set the date according to universal time.
1775
+ * @example
1776
+ *
1777
+ * new Date().set({ year: 2011, month: 11, day: 31 }) -> December 31, 2011
1778
+ * new Date().set(2011, 11, 31) -> December 31, 2011
1779
+ * new Date().set(86400000) -> 1 day after Jan 1, 1970
1780
+ * new Date().set({ year: 2004, month: 6 }, true) -> June 1, 2004, 00:00:00.000
1781
+ *
1782
+ ***/
1783
+ 'set': function() {
1784
+ var args = collectDateArguments(arguments);
1785
+ return updateDate(this, args[0], args[1])
1786
+ },
1787
+
1788
+ /***
1789
+ * @method setUTC()
1790
+ * @set set
1791
+ ***/
1792
+ 'setUTC': function() {
1793
+ var args = collectDateArguments(arguments);
1794
+ return updateDate(this, args[0], args[1], true)
1795
+ },
1796
+
1797
+ /***
1798
+ * @method setWeekday()
1799
+ * @returns Nothing
1800
+ * @short Sets the weekday of the date.
1801
+ * @extra %setUTCWeekday% sets according to universal time.
1802
+ * @example
1803
+ *
1804
+ * d = new Date(); d.setWeekday(1); d; -> Monday of this week
1805
+ * d = new Date(); d.setWeekday(6); d; -> Saturday of this week
1806
+ *
1807
+ ***/
1808
+ 'setWeekday': function(dow) {
1809
+ if(isUndefined(dow)) return;
1810
+ this.setDate(this.getDate() + dow - this.getDay());
1811
+ },
1812
+
1813
+ /***
1814
+ * @method setUTCWeekday()
1815
+ * @set setWeekday
1816
+ ***/
1817
+ 'setUTCWeekday': function(dow) {
1818
+ if(isUndefined(dow)) return;
1819
+ this.setDate(this.getUTCDate() + dow - this.getDay());
1820
+ },
1821
+
1822
+ /***
1823
+ * @method setWeek()
1824
+ * @returns Nothing
1825
+ * @short Sets the week (of the year).
1826
+ * @extra %setUTCWeek% sets according to universal time.
1827
+ * @example
1828
+ *
1829
+ * d = new Date(); d.setWeek(15); d; -> 15th week of the year
1830
+ *
1831
+ ***/
1832
+ 'setWeek': function(week) {
1833
+ if(isUndefined(week)) return;
1834
+ var date = this.getDate();
1835
+ this.setMonth(0);
1836
+ this.setDate((week * 7) + 1);
1837
+ },
1838
+
1839
+ /***
1840
+ * @method setUTCWeek()
1841
+ * @set setWeek
1842
+ ***/
1843
+ 'setUTCWeek': function(week) {
1844
+ if(isUndefined(week)) return;
1845
+ var date = this.getUTCDate();
1846
+ this.setMonth(0);
1847
+ this.setUTCDate((week * 7) + 1);
1848
+ },
1849
+
1850
+ /***
1851
+ * @method getWeek()
1852
+ * @returns Number
1853
+ * @short Gets the date's week (of the year).
1854
+ * @extra %getUTCWeek% gets the time according to universal time.
1855
+ * @example
1856
+ *
1857
+ * new Date().getWeek() -> today's week of the year
1858
+ *
1859
+ ***/
1860
+ 'getWeek': function() {
1861
+ return getWeekNumber(this);
1862
+ },
1863
+
1864
+ /***
1865
+ * @method getUTCWeek()
1866
+ * @set getWeek
1867
+ ***/
1868
+ 'getUTCWeek': function() {
1869
+ return getWeekNumber(this.toUTC());
1870
+ },
1871
+
1872
+ /***
1873
+ * @method getUTCOffset([iso])
1874
+ * @returns String
1875
+ * @short Returns a string representation of the offset from UTC time. If [iso] is true the offset will be in ISO8601 format.
1876
+ * @example
1877
+ *
1878
+ * new Date().getUTCOffset() -> "+0900"
1879
+ * new Date().getUTCOffset(true) -> "+09:00"
1880
+ *
1881
+ ***/
1882
+ 'getUTCOffset': function(iso) {
1883
+ var offset = this.utc ? 0 : this.getTimezoneOffset();
1884
+ var colon = iso === true ? ':' : '';
1885
+ if(!offset && iso) return 'Z';
1886
+ return (-offset / 60).round().pad(2, true) + colon + (offset % 60).pad(2);
1887
+ },
1888
+
1889
+ /***
1890
+ * @method toUTC()
1891
+ * @returns Date
1892
+ * @short Converts the date to UTC time, effectively subtracting the timezone offset.
1893
+ * @extra Note here that the method %getTimezoneOffset% will still show an offset even after this method is called, as this method effectively just rewinds the date. %format% however, will correctly set the %{tz}% (timezone) token as UTC once this method has been called on the date. Once a date is set to UTC the only way to unset is the %clone% method.
1894
+ * @example
1895
+ *
1896
+ * new Date().toUTC() -> current time in UTC
1897
+ *
1898
+ ***/
1899
+ 'toUTC': function() {
1900
+ if(this.utc) return this;
1901
+ var d = this.clone().addMinutes(this.getTimezoneOffset());
1902
+ d.utc = true;
1903
+ return d;
1904
+ },
1905
+
1906
+ /***
1907
+ * @method isUTC()
1908
+ * @returns Boolean
1909
+ * @short Returns true if the date has no timezone offset.
1910
+ * @example
1911
+ *
1912
+ * new Date().isUTC() -> true or false?
1913
+ *
1914
+ ***/
1915
+ 'isUTC': function() {
1916
+ return this.utc || this.getTimezoneOffset() === 0;
1917
+ },
1918
+
1919
+ /***
1920
+ * @method advance()
1921
+ * @returns Date
1922
+ * @short Sets the date forward.
1923
+ * @extra This method can accept multiple formats including a single number as a timestamp, an object, or enumerated parameters (as with the Date constructor). For more see @date_format.
1924
+ * @example
1925
+ *
1926
+ * new Date().advance({ year: 2 }) -> 2 years in the future
1927
+ * new Date().advance(0, 2, 3) -> 2 months 3 days in the future
1928
+ * new Date().advance(86400000) -> 1 day in the future
1929
+ *
1930
+ ***/
1931
+ 'advance': function(params) {
1932
+ var args = collectDateArguments(arguments);
1933
+ return updateDate(this, args[0], false, false, 1, true);
1934
+ },
1935
+
1936
+ /***
1937
+ * @method rewind()
1938
+ * @returns Date
1939
+ * @short Sets the date back.
1940
+ * @extra This method can accept multiple formats including a single number as a timestamp, an object, or enumerated parameters (as with the Date constructor). For more see @date_format.
1941
+ * @example
1942
+ *
1943
+ * new Date().rewind({ year: 2 }) -> 2 years in the past
1944
+ * new Date().rewind(0, 2, 3) -> 2 months 3 days in the past
1945
+ * new Date().rewind(86400000) -> 1 day in the past
1946
+ *
1947
+ ***/
1948
+ 'rewind': function(params) {
1949
+ var args = collectDateArguments(arguments);
1950
+ return updateDate(this, args[0], false, false, -1);
1951
+ },
1952
+
1953
+ /***
1954
+ * @method isValid()
1955
+ * @returns Boolean
1956
+ * @short Returns true if the date is valid.
1957
+ * @example
1958
+ *
1959
+ * new Date().isValid() -> true
1960
+ * new Date('flexor').isValid() -> false
1961
+ *
1962
+ ***/
1963
+ 'isValid': function() {
1964
+ return !isNaN(this.getTime());
1965
+ },
1966
+
1967
+ /***
1968
+ * @method isAfter(<d>, [margin])
1969
+ * @returns Boolean
1970
+ * @short Returns true if the date is after the <d>.
1971
+ * @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 information.
1972
+ * @example
1973
+ *
1974
+ * new Date().isAfter('tomorrow') -> false
1975
+ * new Date().isAfter('yesterday') -> true
1976
+ *
1977
+ ***/
1978
+ 'isAfter': function(d, margin) {
1979
+ return this.getTime() > date.create(d).getTime() - (margin || 0);
1980
+ },
1981
+
1982
+ /***
1983
+ * @method isBefore(<d>, [margin])
1984
+ * @returns Boolean
1985
+ * @short Returns true if the date is before <d>.
1986
+ * @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 information.
1987
+ * @example
1988
+ *
1989
+ * new Date().isBefore('tomorrow') -> true
1990
+ * new Date().isBefore('yesterday') -> false
1991
+ *
1992
+ ***/
1993
+ 'isBefore': function(d, margin) {
1994
+ return this.getTime() < date.create(d).getTime() + (margin || 0);
1995
+ },
1996
+
1997
+ /***
1998
+ * @method isBetween(<d1>, <d2>, [buffer] = 0)
1999
+ * @returns Boolean
2000
+ * @short Returns true if the date falls between <d1> and <d2>.
2001
+ * @extra [buffer] is to allow extra buffer 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 information.
2002
+ * @example
2003
+ *
2004
+ * new Date().isBetween('yesterday', 'tomorrow') -> true
2005
+ * new Date().isBetween('last year', '2 years ago') -> false
2006
+ *
2007
+ ***/
2008
+ 'isBetween': function(d1, d2, buffer) {
2009
+ var t = this.getTime();
2010
+ var t1 = date.create(d1).getTime();
2011
+ var t2 = date.create(d2).getTime();
2012
+ var lo = Math.min(t1, t2);
2013
+ var hi = Math.max(t1, t2);
2014
+ buffer = buffer || 0;
2015
+ return (lo - buffer < t) && (hi + buffer > t);
2016
+ },
2017
+
2018
+ /***
2019
+ * @method isLeapYear()
2020
+ * @returns Boolean
2021
+ * @short Returns true if the date is a leap year.
2022
+ * @example
2023
+ *
2024
+ * Date.create('2000').isLeapYear() -> true
2025
+ *
2026
+ ***/
2027
+ 'isLeapYear': function() {
2028
+ var year = this.getFullYear();
2029
+ return (year % 4 === 0 && year % 100 !== 0) || (year % 400 === 0);
2030
+ },
2031
+
2032
+ /***
2033
+ * @method daysInMonth()
2034
+ * @returns Number
2035
+ * @short Returns the number of days in the date's month.
2036
+ * @example
2037
+ *
2038
+ * Date.create('May').daysInMonth() -> 31
2039
+ * Date.create('February, 2000').daysInMonth() -> 29
2040
+ *
2041
+ ***/
2042
+ 'daysInMonth': function() {
2043
+ return 32 - new date(this.getFullYear(), this.getMonth(), 32).getDate();
2044
+ },
2045
+
2046
+ /***
2047
+ * @method format(<format>, [locale] = currentLocale)
2048
+ * @returns String
2049
+ * @short Formats the date.
2050
+ * @extra <format> will accept a number of tokens as well as pre-determined formats. [locale] specifies a locale code to use (if not specified the current locale is used). If <format> is falsy, a default format for the locale is used. A function may also be passed here to allow more granular control. See @date_format for more details.
2051
+ * @example
2052
+ *
2053
+ * Date.create().format() -> ex. July 4, 2003
2054
+ * Date.create().format('{Weekday} {d} {Month}, {yyyy}') -> ex. Monday July 4, 2003
2055
+ * Date.create().format('{hh}:{mm}') -> ex. 15:57
2056
+ * Date.create().format('{12hr}:{mm}{tt}') -> ex. 3:57pm
2057
+ * Date.create().format(Date.ISO8601_DATETIME) -> ex. 2011-07-05 12:24:55.528Z
2058
+ * Date.create('last week').format('', 'ja') -> ex. 先週
2059
+ * Date.create('yesterday').format(function(value,unit,ms,loc) {
2060
+ * // value = 1, unit = 3, ms = -86400000, loc = [current locale object]
2061
+ * }); -> ex. 1 day ago
2062
+ *
2063
+ ***/
2064
+ 'format': function(f, locale) {
2065
+ return formatDate(this, f, false, locale);
2066
+ },
2067
+
2068
+ /***
2069
+ * @method relative([fn], [locale] = currentLocale)
2070
+ * @returns String
2071
+ * @short Returns a relative date string offset to the current time.
2072
+ * @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 information, see @date_format.
2073
+ * @example
2074
+ *
2075
+ * Date.create('90 seconds ago').relative() -> 1 minute ago
2076
+ * Date.create('January').relative() -> ex. 5 months ago
2077
+ * Date.create('January').relative('ja') -> 3ヶ月前
2078
+ * Date.create('120 minutes ago').relative(function(val,unit,ms,loc) {
2079
+ * // value = 2, unit = 3, ms = -7200, loc = [current locale object]
2080
+ * }); -> ex. 5 months ago
2081
+ *
2082
+ ***/
2083
+ 'relative': function(f, locale) {
2084
+ if(object.isString(f)) {
2085
+ locale = f;
2086
+ f = null;
2087
+ }
2088
+ return formatDate(this, f, true, locale);
2089
+ },
2090
+
2091
+ /***
2092
+ * @method is(<d>, [margin])
2093
+ * @returns Boolean
2094
+ * @short Returns true if the date is <d>.
2095
+ * @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 information, see @date_format.
2096
+ * @example
2097
+ *
2098
+ * Date.create().is('July') -> true or false?
2099
+ * Date.create().is('1776') -> false
2100
+ * Date.create().is('today') -> true
2101
+ * Date.create().is('weekday') -> true or false?
2102
+ * Date.create().is('July 4, 1776') -> false
2103
+ * Date.create().is(-6106093200000) -> false
2104
+ * Date.create().is(new Date(1776, 6, 4)) -> false
2105
+ *
2106
+ ***/
2107
+ 'is': function(d, margin) {
2108
+ var tmp;
2109
+ if(object.isString(d)) {
2110
+ d = d.trim().toLowerCase();
2111
+ switch(true) {
2112
+ case d === 'future': return this.getTime() > new date().getTime();
2113
+ case d === 'past': return this.getTime() < new date().getTime();
2114
+ case d === 'weekday': return this.getDay() > 0 && this.getDay() < 6;
2115
+ case d === 'weekend': return this.getDay() === 0 || this.getDay() === 6;
2116
+ case (tmp = English['weekdays'].indexOf(d) % 7) > -1: return this.getDay() === tmp;
2117
+ case (tmp = English['months'].indexOf(d) % 12) > -1: return this.getMonth() === tmp;
2118
+ }
2119
+ }
2120
+ return compareDate(this, d, margin);
2121
+ },
2122
+
2123
+ /***
2124
+ * @method resetTime()
2125
+ * @returns Date
2126
+ * @short Resets the time in the date to 00:00:00.000.
2127
+ * @example
2128
+ *
2129
+ * Date.create().resetTime() -> Beginning of today
2130
+ *
2131
+ ***/
2132
+ 'resetTime': function() {
2133
+ return this.set({ 'hour': 0, 'minute': 0, 'second': 0, 'millisecond': 0 });
2134
+ },
2135
+
2136
+ /***
2137
+ * @method clone()
2138
+ * @returns Date
2139
+ * @short Clones the date.
2140
+ * @example
2141
+ *
2142
+ * Date.create().clone() -> Copy of now
2143
+ *
2144
+ ***/
2145
+ 'clone': function() {
2146
+ return new date(this.getTime());
2147
+ }
2148
+
2149
+ });
2150
+
2151
+
2152
+ // Instance aliases
2153
+ date.extend({
2154
+
2155
+ /***
2156
+ * @method iso()
2157
+ * @alias toISOString
2158
+ *
2159
+ ***/
2160
+ 'iso': function() {
2161
+ return this.toISOString();
2162
+ },
2163
+
2164
+ /***
2165
+ * @method getWeekday()
2166
+ * @alias getDay
2167
+ *
2168
+ ***/
2169
+ 'getWeekday': date.prototype.getDay,
2170
+
2171
+ /***
2172
+ * @method getUTCWeekday()
2173
+ * @alias getUTCDay
2174
+ *
2175
+ ***/
2176
+ 'getUTCWeekday': date.prototype.getUTCDay
2177
+
2178
+ });
2179
+
2180
+
2181
+
2182
+ /***
2183
+ * Number module
2184
+ *
2185
+ ***/
2186
+
2187
+ number.extend({
2188
+
2189
+ /***
2190
+ * @method duration([locale] = currentLocale)
2191
+ * @returns String
2192
+ * @short Takes the number as milliseconds and returns a unit-adjusted localized string.
2193
+ * @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.
2194
+ * @example
2195
+ *
2196
+ * (500).duration() -> '500 milliseconds'
2197
+ * (1200).duration() -> '1 second'
2198
+ * (75).minutes().duration() -> '1 hour'
2199
+ * (75).minutes().duration('es') -> '1 hora'
2200
+ *
2201
+ ***/
2202
+ 'duration': function(code) {
2203
+ return Date.getLocale(code).duration(this);
2204
+ }
2205
+
2206
+ });
2207
+
2208
+ buildDate();
2209
+
2210
+ })();